WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.146 --> 00:00:06.216 align:middle
When we click the heart icon, we need to
send an AJAX request to the server that will,

00:00:06.216 --> 00:00:11.446 align:middle
eventually, update something in a database
to show that the we liked this article.

00:00:12.446 --> 00:00:18.206 align:middle
That API endpoint also needs to return the
new number of hearts to show on the page...

00:00:18.456 --> 00:00:18.836 align:middle
ya know...

00:00:19.286 --> 00:00:22.376 align:middle
in case 10 other people liked
it since we opened the page.

00:00:22.376 --> 00:00:30.276 align:middle
In ArticleController, make a new
public function toggleArticleHeart().

00:00:31.826 --> 00:00:42.316 align:middle
Then add the route above: @Route("/news/{slug}")
- to match the show URL - then /heart.

00:00:43.716 --> 00:00:48.056 align:middle
Give it a name immediately:
article_toggle_heart.

00:00:49.216 --> 00:00:54.866 align:middle
I included the {slug} wildcard in the route
so that we know which article is being liked.

00:00:55.816 --> 00:00:59.746 align:middle
We could also use an {id}
wildcard once we have a database.

00:01:00.726 --> 00:01:02.626 align:middle
Add the corresponding $slug argument.

00:01:03.446 --> 00:01:10.756 align:middle
But since we don't have a database yet, I'll
add a TODO: actually heart/unheart the article!.

00:01:13.646 --> 00:01:17.016 align:middle
We want this API endpoint to return JSON...

00:01:17.216 --> 00:01:21.436 align:middle
and remember: the only rule
for a Symfony controller is

00:01:21.436 --> 00:01:24.506 align:middle
that it must return a Symfony Response object.

00:01:25.116 --> 00:01:32.436 align:middle
So we could literally say return new
Response(json_encode(['hearts' =&gt; 5])).

00:01:34.336 --> 00:01:35.416 align:middle
But that's too much work!

00:01:36.236 --> 00:01:44.756 align:middle
Instead say return new JsonResponse(['hearts'
=&gt; rand(5, 100)].

00:01:45.806 --> 00:01:51.046 align:middle
There's nothing special here:
JsonResponse is a sub-class of Response.

00:01:51.726 --> 00:01:59.256 align:middle
It calls json_encode for you, and also sets
the Content-Type header to application/json,

00:01:59.456 --> 00:02:01.866 align:middle
which helps your JavaScript understand things.

00:02:03.186 --> 00:02:04.786 align:middle
Let's try this in the browser first.

00:02:05.236 --> 00:02:07.886 align:middle
Go back and add /heart to the URL.

00:02:09.776 --> 00:02:12.956 align:middle
Yes! Our first API endpoint!

00:02:13.716 --> 00:02:19.576 align:middle
Eventually, this endpoint will modify something
on the server - it will "like" the article.

00:02:20.376 --> 00:02:25.356 align:middle
So as a best-practice, we should not
be able to make a GET request to it.

00:02:26.346 --> 00:02:29.966 align:middle
Let's make this route only match
when a POST request is made.

00:02:30.866 --> 00:02:36.506 align:middle
How? Add another option to
the route: methods={"POST"}.

00:02:39.276 --> 00:02:43.986 align:middle
As soon as we do that, we can no longer
make a GET request in the browser:

00:02:44.486 --> 00:02:46.636 align:middle
it does not match the route anymore!

00:02:48.106 --> 00:02:52.716 align:middle
Run: ./bin/console debug:router and you'll see

00:02:52.716 --> 00:02:56.076 align:middle
that the new route only responds
to POST requests.

00:02:56.916 --> 00:02:57.496 align:middle
Pretty cool.

00:02:58.276 --> 00:03:01.126 align:middle
By the way, Symfony has a lot more tools

00:03:01.126 --> 00:03:04.926 align:middle
for creating API endpoints -
this is just the beginning.

00:03:05.466 --> 00:03:07.546 align:middle
In future tutorials, we'll go further!

00:03:09.236 --> 00:03:11.186 align:middle
Our API endpoint is ready!

00:03:11.716 --> 00:03:14.916 align:middle
Copy the route name and go
back to article_show.js.

00:03:14.916 --> 00:03:15.266 align:middle
But wait...

00:03:15.526 --> 00:03:20.766 align:middle
if we want to make an AJAX
request to the new route...

00:03:20.766 --> 00:03:23.376 align:middle
how can we generate the URL?

00:03:24.176 --> 00:03:26.276 align:middle
This is a pure JS file...

00:03:26.456 --> 00:03:29.326 align:middle
so we can't use the Twig path() function!

00:03:30.126 --> 00:03:36.896 align:middle
Actually, there is a really cool bundle
called FOSJsRoutingBundle that does allow you

00:03:36.896 --> 00:03:38.826 align:middle
to generate routes in JavaScript.

00:03:39.486 --> 00:03:42.016 align:middle
But, I'm going to show you another, simple way.

00:03:43.156 --> 00:03:45.606 align:middle
Back in the template, find the heart section.

00:03:46.536 --> 00:03:47.096 align:middle
Let's just...

00:03:47.456 --> 00:03:49.386 align:middle
fill in the href on the link!

00:03:49.386 --> 00:03:57.326 align:middle
Add path(), paste the route name, and pass
the slug wildcard set to a slug variable.

00:03:58.646 --> 00:03:59.246 align:middle
Actually...

00:03:59.526 --> 00:04:02.666 align:middle
there is not a slug variable
in this template yet.

00:04:03.346 --> 00:04:07.026 align:middle
If you look at ArticleController,
we're only passing two variables.

00:04:08.206 --> 00:04:11.846 align:middle
Add a third: slug set to $slug.

00:04:13.216 --> 00:04:16.366 align:middle
That should at least set the URL on the link.

00:04:18.076 --> 00:04:20.676 align:middle
Go back to the show page in
your browser and refresh.

00:04:24.256 --> 00:04:26.846 align:middle
Yep! The heart link is hooked up.

00:04:28.196 --> 00:04:30.036 align:middle
Why did we do this?

00:04:30.746 --> 00:04:34.966 align:middle
Because now we can get that URL
really easily in JavaScript.

00:04:35.626 --> 00:04:47.216 align:middle
Add $.ajax({}) and pass method: 'POST'
and url set to $link.attr('href').

00:04:47.216 --> 00:04:47.766 align:middle
That's it!

00:04:48.376 --> 00:04:53.386 align:middle
At the end, add .done() with a
callback that has a data argument.

00:04:54.546 --> 00:04:57.906 align:middle
The data will be whatever
our API endpoint sends back.

00:04:58.776 --> 00:05:06.136 align:middle
That means that we can move the article count
HTML line into this, and set it to data.heart.

00:05:07.406 --> 00:05:11.196 align:middle
Oh, and if you're not familiar with
the .done() function or Promises,

00:05:11.476 --> 00:05:14.606 align:middle
I'd highly recommend checking
out our JavaScript Track.

00:05:15.176 --> 00:05:19.716 align:middle
It's not beginner stuff: it's meant
to take your JS up to the next level.

00:05:20.926 --> 00:05:21.446 align:middle
Anyways...

00:05:21.716 --> 00:05:22.986 align:middle
let's try it already!

00:05:23.436 --> 00:05:25.656 align:middle
Refresh! And...

00:05:25.656 --> 00:05:28.686 align:middle
click! It works!

00:05:29.126 --> 00:05:31.186 align:middle
And... I have a surprise!

00:05:31.186 --> 00:05:34.976 align:middle
See this little arrow icon
in the web debug toolbar?

00:05:35.716 --> 00:05:39.766 align:middle
This showed up as soon as we
made the first AJAX request.

00:05:40.736 --> 00:05:45.496 align:middle
Actually, every time we make an AJAX
request, it's added to the top of this list!

00:05:46.256 --> 00:05:49.606 align:middle
That's awesome because - remember the profiler?

00:05:50.186 --> 00:05:54.766 align:middle
- you can click to view the
profiler for any AJAX request.

00:05:55.866 --> 00:06:00.586 align:middle
Yep, you now have all the performance
and debugging tools at your fingertips...

00:06:01.076 --> 00:06:02.776 align:middle
even for AJAX calls.

00:06:03.946 --> 00:06:08.636 align:middle
Oh, and if there were an error, you
would see it in all its beautiful,

00:06:08.796 --> 00:06:11.166 align:middle
styled glory on the Exception tab.

00:06:12.176 --> 00:06:15.466 align:middle
Being able to load the profiler
for an AJAX call is kind

00:06:15.466 --> 00:06:18.216 align:middle
of an easter egg: not everyone knows about it.

00:06:18.546 --> 00:06:19.886 align:middle
But you should.

00:06:19.886 --> 00:06:25.696 align:middle
I think it's time to talk about the
most important part of Symfony: Fabien.

00:06:26.026 --> 00:06:27.636 align:middle
I mean, services.

