Buy

Hooking up the Scientist Removal JavaScript

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:

91 lines app/Resources/views/genus/show.html.twig
... 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:

91 lines app/Resources/views/genus/show.html.twig
... 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:

91 lines app/Resources/views/genus/show.html.twig
... 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:

91 lines app/Resources/views/genus/show.html.twig
... 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:

91 lines app/Resources/views/genus/show.html.twig
... 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...

Leave a comment!

  • 2017-05-12 Victor Bocharsky

    Hey Kuba,

    Fair point! That's another reason to avoid setting URL in href attribute - avoid such 404 errors :)

    Cheers!

  • 2017-05-10 Kuba Florczuk

    Remember that you've set method to DELETE, while following link without JS will fire GET method, so user will probably get 404 and nothing will happen.

  • 2017-04-07 Victor Bocharsky

    Hey Richard,

    Setting URL in href probably requires more work, since if user has disabled JS in they browser - they will follow this link on click. But with data-url nothing happens. So you can set it in href, but then probably you have to handle this case, e.g. return JSON response if AJAX request was sent and do redirecting if user follows this link without JS. And one more thing: your website most probably is scanned by different robots like google crawler, etc. and most of them do not support JS, that's why they will follow this link to, but probably it's not something you want for JS links, but it depends. So it's up to you what to use, but data-url is more mainstream now, so you'll see using it more by us :)

    Cheers!

  • 2017-04-05 Richard Perez

    Probably no the best place to ask, but why to use a `data-url` instead of using the `href` attribute? You are still using the e.preventDefault() so nothing will happen. I saw it in another of your tutorials and now I'm curious.

  • 2016-12-16 Victor Bocharsky

    Yes, several chapters of the first course should be released at the end of this month or in Jan 2017 :)

    Cheers!

  • 2016-12-16 somecallmetim27

    That's awesome!!! Would definitely LOVE LOVE LOVE to get my hands on the React.js course. I know that that and Angular are really popular right now. :)

    Any idea on a time frame for any of the planned JS courses? I notice the first one already seems to have some kind of lesson plan. :D

  • 2016-12-12 Victor Bocharsky

    Hey Connect,

    jQuery is pretty simple and has a good docs with ton of examples: http://api.jquery.com/ - but you're right... And we're working on it right now: https://knpuniversity.com/s... ! It will cover some most useful jQuery methods, which we use a lot in our screencasts and much more! So you can subscribe to it and we'll notify you when this course is released.

    Cheers!

  • 2016-12-11 Connect James

    Hi Ryan, looking at this course I was thinking it would be really cool to have a short course on a few jQuery methods that you use a lot in relation with the Symfony framework.