Hooking up the Scientist Removal JavaScript
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
Endpoint, done! Let's call this bad boy from JavaScript. Back in the template, each
delete link will have a different URL to the endpoint. Add a new attribute called
data-url
set to path('genus_scientist_remove')
and pass it genusId
set to
genus.id
and userId
set to genusScientist.id
. Remember, that's a User
object:
// ... lines 1 - 4 | |
{% block body %} | |
<h2 class="genus-name">{{ genus.name }}</h2> | |
<div class="sea-creature-container"> | |
<div class="genus-photo"></div> | |
<div class="genus-details"> | |
<dl class="genus-details-list"> | |
// ... lines 12 - 21 | |
<dd> | |
<ul class="list-group"> | |
{% for genusScientist in genus.genusScientists %} | |
<li class="list-group-item js-scientist-item"> | |
// ... lines 26 - 31 | |
<a href="#" | |
class="btn btn-link btn-xs pull-right js-remove-scientist-user" | |
data-url="{{ path('genus_scientists_remove', { | |
genusId: genus.id, | |
userId: genusScientist.id | |
}) }}" | |
> | |
<span class="fa fa-close"></span> | |
</a> | |
</li> | |
{% endfor %} | |
</ul> | |
</dd> | |
</dl> | |
</div> | |
</div> | |
<div id="js-notes-wrapper"></div> | |
{% endblock %} | |
// ... lines 50 - 91 |
Oh, and do one more thing: give the li
above its own class: js-scientist-item
:
// ... lines 1 - 4 | |
{% block body %} | |
<h2 class="genus-name">{{ genus.name }}</h2> | |
<div class="sea-creature-container"> | |
<div class="genus-photo"></div> | |
<div class="genus-details"> | |
<dl class="genus-details-list"> | |
// ... lines 12 - 21 | |
<dd> | |
<ul class="list-group"> | |
{% for genusScientist in genus.genusScientists %} | |
<li class="list-group-item js-scientist-item"> | |
// ... lines 26 - 40 | |
</li> | |
{% endfor %} | |
</ul> | |
</dd> | |
</dl> | |
</div> | |
</div> | |
<div id="js-notes-wrapper"></div> | |
{% endblock %} | |
// ... lines 50 - 91 |
That'll also help in JavaScript.
Making the AJAX Call
Scroll back to the javascripts
block. I'll paste a few lines of code here to get
us started:
// ... lines 1 - 50 | |
{% block javascripts %} | |
// ... lines 52 - 66 | |
<script> | |
jQuery(document).ready(function() { | |
$('.js-remove-scientist-user').on('click', function(e) { | |
e.preventDefault(); | |
var $el = $(this).closest('.js-scientist-item'); | |
$(this).find('.fa-close') | |
.removeClass('fa-close') | |
.addClass('fa-spinner') | |
.addClass('fa-spin'); | |
// ... lines 78 - 86 | |
}); | |
}); | |
</script> | |
{% endblock %} |
Ok, no big deal: the first line uses $(this)
, which is the link that was just clicked,
and finds the .js-scientist-item
li that is around it. We'll use that in a minute.
The second chunk changes the fa-close
icon into a loading spinner... ya know...
because we deserve fancy things.
The real work - the AJAX call - is up to us. I'll use $.ajax()
. Set the url
key to $(this).data('url')
to read the attribute we just set. And then, set
method
to DELETE
:
// ... lines 1 - 50 | |
{% block javascripts %} | |
// ... lines 52 - 66 | |
<script> | |
jQuery(document).ready(function() { | |
$('.js-remove-scientist-user').on('click', function(e) { | |
e.preventDefault(); | |
var $el = $(this).closest('.js-scientist-item'); | |
$(this).find('.fa-close') | |
.removeClass('fa-close') | |
.addClass('fa-spinner') | |
.addClass('fa-spin'); | |
$.ajax({ | |
url: $(this).data('url'), | |
method: 'DELETE' | |
// ... lines 82 - 83 | |
}); | |
// ... lines 85 - 86 | |
}); | |
}); | |
</script> | |
{% endblock %} |
To add a little bit more fancy, add a .done()
. After the AJAX call finishes,
call $el.fadeOut()
so that the item disappears in dramatic fashion:
// ... lines 1 - 50 | |
{% block javascripts %} | |
// ... lines 52 - 66 | |
<script> | |
jQuery(document).ready(function() { | |
$('.js-remove-scientist-user').on('click', function(e) { | |
// ... lines 70 - 78 | |
$.ajax({ | |
url: $(this).data('url'), | |
method: 'DELETE' | |
}).done(function() { | |
$el.fadeOut(); | |
}); | |
// ... lines 85 - 86 | |
}); | |
}); | |
</script> | |
{% endblock %} |
Testing time! Refresh.
Cute close icon, check! Click it! It faded away in dramatic fashion! Yes!
Checking the Delete Query
Check out the web debug toolbar's AJAX icon. Mixed in with AJAX call for notes is our DELETE call. Click the little sha, then go to the Doctrine tab. Ooh, look at this:
DELETE FROM genus_scientist WHERE genus_id = 11 AND user_id = 11
Gosh darn it that's nice. To prove it, refresh: the scientist is gone. ManyToMany? Yea, it's as simple as adding and removing objects from an array.
Well, ok, it will get a bit harder soon...
Off topic: I want to upload an undefined amount of input fields on the database. Its an undefined amount, because the amount of input fields depend on the amount of 'Meetstaten', which is different on every product. But I think it's uploading a string instead of a float.