00:00
[MUSIC]
00:05
Now the fun begins.
00:06
Let's go ahead and create a page inside of our application that
00:08
lists all Cineasts who have directed any movies.
00:11
Then from there, we'll create a show page for that director,
00:14
listing all of the movies that they've directed.
00:17
Let's hit "Command P" and type in routes to jump into our routes file.
00:20
Underneath our movie show page,
00:21
let's go ahead and add in an additional page.
00:23
So router.get/, we'll call this directors.
00:26
Then if we stop and take a look at our controllers,
00:29
we don't have a controller applicable for this.
00:31
So let's dive into our terminal and let's run node,
00:33
ace, make, controller, directors.
00:36
Then we'll also want to stop it with a method called index.
00:39
So add index there to the end of this command. Let's run that.
00:42
There we go. So now we have a director's controller
00:44
with an index method stopped inside of it.
00:46
So we can type out director's controller,
00:48
hit tab to auto-import that just like so.
00:50
Once we save that, we'll switch to the correct lazy import here,
00:53
and we'll use the index method there since this will be
00:55
our listing page that will list all directors that we have.
00:58
So we'll call this as directors.index.
01:02
Once we save, we saw this switch from an orange tint
01:04
to a purple tint indicating that it did switch to a lazy import.
01:07
We'll hold option down to switch that to
01:10
down below our router import there
01:11
to keep all of our controller imports together.
01:13
Jump over to our director's controller,
01:15
and there is our stubbed index method.
01:17
Out of our HTTP context, let's grab our view,
01:19
and let's go and just start by returning view,
01:22
render pages/directors/show.
01:26
Let's create that page real quick.
01:28
Let's also go ahead and delete out the movies that we have
01:30
inside of our resources movies directory.
01:31
So we'll hit delete there, move that to the trash.
01:34
Let's go ahead and right-click that, new file,
01:36
add a folder called directors/,
01:38
and whoops, we're still on the index method,
01:40
so we'll want that to be called index, not show.
01:42
My bad there. So index.edge.
01:44
Let's jump back into our director's controller
01:45
and fix that real quick.
01:46
So instead of show, we do want this to be called index.
01:49
Okay, there we go.
01:50
So we'll do @layout, @ender layout,
01:53
and we'll just do an h1 of directors
01:55
so that we have something listing out this page.
01:58
Let's go ahead and dive into our partials
01:59
for our navigation,
02:00
and let's add in an additional anchor, href,
02:03
pointing to our route, directors.index,
02:07
and we'll call this directors.
02:08
Okay, give that a save.
02:10
We should now be able to jump into our terminal
02:11
and pm run dev to boot up our server.
02:13
Let's open up our browser.
02:15
Okay, here's our homepage.
02:16
If we click into directors now,
02:18
we get an h1 with directors.
02:19
Awesome. Let's hide that back away,
02:21
jump back into our text editor,
02:22
and let's go back to our director's controller.
02:24
We'll do const directors equals await.
02:28
We'll want to query from our Cynist model,
02:30
so we'll import that.
02:31
We're going to want to use the Cynist models query builder.
02:34
Now, we're going to want to query all Cineasts
02:36
who have a movie where they are the director ID.
02:39
So we're going to want to use,
02:41
if we dive into our Cynist model,
02:42
the movie's directed relationship
02:44
to check and see whether or not they have any records.
02:47
So for that, we could do where has
02:50
to check the existence of a relationship.
02:53
Whenever we hit the strings, we get IntelliSense popping up
02:55
that we have movies directed available to us.
02:58
If we needed to, we could provide a callback function
03:00
as the second argument here to extend
03:03
the movies directed query to add
03:05
additional statements to those movies.
03:07
For example, if the Cynist has
03:08
only directed movies that aren't out yet,
03:10
maybe we don't want to include them in this list.
03:12
So we could go ahead and apply a query scope
03:15
to our movies directed relationship from our movies query,
03:18
and this will be our movies query builder here.
03:21
So we have access to our scope.releasedQueryScope.
03:25
Now, if we hit "Save", the red squiggly is just due to formatting.
03:28
So there we go. Now, we should have directors who
03:31
have directed any movie that's already been released.
03:34
So we can provide that into our directors index as directors.
03:38
Let's dive back into that page.
03:40
For now, let's just do a ul,
03:42
each to loop over them,
03:43
director in directors at end are each,
03:47
and then we'll do an align here with our director full name.
03:51
Give that a save and let's go check it out to see if everything worked.
03:53
Jump back into our browser, and there we go.
03:55
Now, at this point, it's a little bit of a random list.
03:58
We don't have any sorting going on.
03:59
So let's fix that real quick.
04:01
Hide that back away, jump back into our directors controller,
04:04
and to the end of our query here,
04:05
we can add on a dot order by,
04:08
and we don't want to order by two columns,
04:10
the first name and then the last name.
04:11
We cannot order by a computed property
04:14
because it does not actually exist inside of the database.
04:17
So we can provide an array into this,
04:18
and in the first index,
04:20
we specify the column that we first want to order by,
04:23
which would be our first name.
04:25
The default direction is going to be ascending,
04:26
but if we need to change that or if we want to explicitly set it,
04:29
we can set it to order by ascending.
04:31
Then we can add in a second index here,
04:33
where the second column that we want to order by
04:35
is last name with the order of ascending there as well.
04:39
Give that a save. So we'll first order by our first name,
04:42
and then once it's done ordering by first name,
04:44
if we have any Sinus record using the same first name,
04:47
they'll then be ordered by the last name.
04:49
Cool. So let's jump back into our browser,
04:50
give that a refresh, and there we go.
04:52
So now they are listed in alphabetical order.
04:54
Now we need to be able to click into them and show
04:56
a details page with the movies that they have directed, listed out.
04:59
So I'll hide this back away.
05:01
So let's scroll down a little bit here,
05:02
and let's do a public show page.
05:04
We'll grab view out of that,
05:06
as well as our params,
05:07
HTTP context, and we'll go ahead and return view,
05:11
render pages, directors, show.
05:14
Before we go any further, let's define the route for this.
05:16
So we'll dive back into our routes.
05:18
Underneath our directors route,
05:20
we'll do router.get directors/,
05:23
and we don't have a slug for our directors,
05:25
and it's possible that directors could have the same first name and last name.
05:28
So for right now, we'll just need to do ID there,
05:31
and we can use the director's controller
05:33
and specify the show method there is directors show.
05:37
Let's round out our circle by diving back into our directors index page,
05:40
and let's add a link around our full name here.
05:43
So we'll do a href route directors show,
05:47
and let's add the param ID of director.ID.
05:52
We'll end our anchor and move that end tag down below our director full name.
05:56
Then we'll need to create our show page.
05:57
So I'm just going to copy everything that we have here
05:59
because it's going to be relatively similar,
06:01
and we can right-click our directors page,
06:03
new file, show.edge, paste that in.
06:07
Instead of directors up here,
06:08
this will instead be director.
06:11
Then we can list out their full name.
06:13
Then for our loop,
06:14
let's just jump back into our homepage,
06:16
and let's copy our div where we're using our cards,
06:19
jump back into our director show page,
06:20
highlight this, give that a paste,
06:22
and we can get rid of our URL.
06:24
Cool. Now, instead of coming soon,
06:26
this will just be all of their movies like so.
06:28
So we give that a save,
06:29
and let's jump into our movie card as well
06:31
because we're still using PIXM here,
06:33
but we have actual poster URLs tied to our movie now.
06:36
So we can replace that PIXM poster URL there as well.
06:40
Close that out because we're done with it.
06:41
Jump back into our director's controller,
06:43
and let's add in the query to get our director from our ID parameter
06:47
and their directed movies.
06:49
So const director equals await
06:51
cinist.findOrFailRams.id.
06:56
So we'll find or fail our cinist by their primary key ID column
07:00
provided into our route parameter ID value.
07:03
This also needs to be an async method.
07:05
There we go. So we can go ahead and add in our director
07:08
into our state for our page,
07:09
and now we need to get their movies.
07:11
So we can do await,
07:12
and for this, we can reach through this director
07:15
to get their related movies via its relationship.
07:18
So we can do director.related to reach through a relationship,
07:23
and we specifically want to use the movie's directed relationship here,
07:26
.query to get that relationship's query builder.
07:29
So now this is a movie query builder
07:31
using the relationship bound to this specific director.
07:35
So let's go ahead and order by that movie's title, okay?
07:38
And let's add the movies into our page state there as well.
07:42
We'll give that a save.
07:43
Let's jump into our browser and see if we got everything right.
07:45
So these are actual links.
07:47
They aren't shown like that because of the TailwindCSS reset,
07:50
but let's go ahead and click into Clark Strosen
07:52
because we were working with him in our last lesson.
07:55
So we know that he is bound to 310 to Yuma.
07:57
So we can click on him, and look at that.
07:59
His very first movie is 310 to Yuma.
08:01
And now we have all of Clark Strosen's directed movies listed out on his page.
08:06
Awesome. We'll add director to the start of the name
08:09
just so that we have that explicit.
08:11
So let's jump back into our show page here,
08:13
and let's do director, full name.
08:15
Okay, so now that should be director Clark Strosen.
08:17
There we go. Awesome.
08:18
So if we go back to our director's page, let's click on somebody else.
08:21
There's another handful of movies.
08:23
Click on somebody else, another handful of movies,
08:26
and let's click on somebody else.
08:27
And this person only has one,
08:29
so they are one of the ones that we created using the with method
08:32
with our movie factory.
08:34
So cool. Everything seems to work.
08:35
And even furthermore, we can click in to see the movie's details page
08:38
from each one of those.
Join The Discussion! (4 Comments)
Please sign in or sign up for free to join in on the dicussion.
nico75
Hey, first, thanks for this full tutorial.
I try to use route with a custom button component
@shared.button({href: "{{route('movie.show', {id: movie.slug})}}", class: ""}) View Details @end
this not work
@shared.button({href: "movies/" + movie.slug, class: ""}) View Details
this work
Is there a way to achieve this ?
Please sign in or sign up for free to reply
tomgobich
Hey Nico! Thanks for watching!
When you're passing props into your button component, you're already inside of an EdgeJS interpolation area. So, at that point you don't need the double-curly braces and adding them will actually mess things up in that context. Instead, you can directly access the route function, like below.
Also, and this might've just been formatting in the comment, but just in case also be sure the start and end tags for your EdgeJS components are on their own lines.
Please sign in or sign up for free to reply
nico75
Thanks a lot. It work now.
I'm going to continue to watch the videos, very helpfull to learn Adonis and Edge !
Please sign in or sign up for free to reply
tomgobich
You're welcome, Nico! Happy to hear all is working now!
Hope you enjoy your time with AdonisJS & Edge! 😊
Please sign in or sign up for free to reply