Scroll down to the script below, click on any sentence (including terminal blocks!) to jump to that spot in the video!Cool, got it!
This Chapter isn't quite ready yet
Rest assured, the gnomes are hard at work on completing this video
Let's copy the original filename code and replace it with
<input type="text" and
value=" that original filename stuff. Let's also
add two classes: one from Bootstrap to make things look nice and another -
detail: add a
style attribute with
width: auto - just another styling thing.
Next: copy the
js- class name and head back up to the constructor. We're going
to do the same thing we did with our delete link:
this.$element.on('blur'), this time with
.js-edit-filename and then our arrow
function. Inside that, call a new function:
and pass that the
Keep going: copy the method name, scroll down a bit, and create that function,
which will accept an
event object. Let's also steal the first two lines from
handleReferenceDelete(): we're going to start the exact same way. Heck, we're
going to make an AJAX request to the same URL! Just with the
PUT method instead
When we send that AJAX request, we're only going to send one piece of data: the
originalFilename that's in the text box. But I want you to pretend that we're
allowing multiple fields to be updated on the reference. So, more abstractly,
what we were really want to do is find the reference that's being updated from
this.references, change the
originalFilename data on it, JSON-encode
that entire object, and send it to the endpoint.
If that doesn't make sense yet, don't worry. To find the reference object that's
being updated right now, say
const reference = this.references.find() and pass
this an arrow function with a reference argument. Inside,
return reference.id === id.
This loops over all the references and returns the first one it finds that matches
the id... which should only be one. Now change the
$(event.currentTarget) - that will give us the input element -
Ok! We're ready to send the AJAX request! Copy the first-half of the AJAX call from
the delete function, remove the
.then() stuff, change the method to
for the data, just pass
There is a small problem with this - so if you see it, hang on! But, the idea is cool: we're sending up all of the reference data. And yes, this will send more fields than we need, but that's ok! The deserializer just ignores that extra stuff.
Testing time! Refresh the whole page. Oh wow - we have an extra
< sign! As cool
as that looks, let's scroll down to render and... there it is - remove that.
Refresh again. Let's tweak the filename and then click off to trigger the "blur". Uh oh!
Cannot set property
Hmm. Look back at our code: for some reason it's not finding our reference. Oh, duh:
return referenced.id === id.
Ok, let's see if I've finally got everything right. Refresh, add a dash to the
filename, click off and... 500 error! That's progress! Open the profiler for
that request in a new tab. Ok: a "Syntax Error" coming from a
class. Oh, and look at the data that's passed to the
That's not JSON!
Silly mistake. When we set the
data key to the
reference object, jQuery doesn't
send up that data as JSON, it uses the standard "form submit" format. We want
I think we've got it this time. Refresh, tweak the filename, click off and... no
errors! Check out the network tab. Yeah
200! The response returns the updated
originalFilename and, if you scroll down to the request body... cool! You can
see the raw JSON that was sent up.
The last thing we need to do is... add validation. I know, it's always that annoying last detail once you've got the "happy" path working perfectly. But, right now, we could leave the filename completely blank and our system would be ok with that. Well ya know what? I am totally not ok with that!
Ultimately, our endpoint modifies the
ArticleReference object and that is
what we should validate. Above the
originalFilename field, add
and let's also use
@Length(). The length can be 255 in the database, but let's
max=100. Then, inside our endpoint, there's no form here, but that's fine.
ValidatorInterface $validator argument. And right after we update the
object with the serializer, add
$violations = $validator->validate() and pass
$reference object. Then if
$violations->count() > 0,
return $this->json($violations, 400).
But let's at least make sure it works. Clear out the filename, hit tab to blur
and... there it is! A 400 error with our beautiful error response. To handle this
.catch() onto the end of the AJAX call and then
do whatever you want.
Ok, what else can we add to our upload widget? How about the ability to reorder the list. That's next.