00:00
(upbeat music)
00:02
So with your HTML forms,
00:06
there's gonna be times where you need to be able to send up
00:08
an array of data or even an array of objects.
00:11
And our cast and crew members
00:13
are one such instance for our movies.
00:15
Let's add them in down here
00:17
just above our update movie button.
00:19
So let's start by jumping into our creator edit page
00:21
right above that button.
00:23
We can give ourselves a little heading to mark
00:24
that this is where they will be.
00:26
Do font bold and just say this is the crew members.
00:30
And we'll just focus on the crew members here for now.
00:32
We will have a div with an ID of crew list.
00:36
This is the div that will list out
00:38
all the crew members attached to the movie within.
00:41
So we'll have this as class, flex, flex column,
00:44
and we'll have one child inside of this list
00:47
per crew member that we are attaching.
00:49
So we'll have a gap of three there as well.
00:51
And in here is where we can do an each to loop over them.
00:54
So we'll do an each member in,
00:56
and we'll call this variable crew members
00:58
whenever we get around to querying it.
01:00
Then we'll end our each.
01:02
And inside of here, we'll have another div class flex,
01:05
and we'll do a gap of three here as well
01:08
because we're gonna have multiple fields.
01:09
The first field that we need to have is a select,
01:12
and the options for the select are gonna be Cineasts.
01:14
So we can copy either our director or writer field
01:17
as a good starting point for this input,
01:20
pasting it in its place.
01:21
The label we can do as crew member.
01:24
The name we will circle back to momentarily,
01:27
whether or not it's selected.
01:29
Instead of doing movie dot something,
01:31
instead we're gonna query this information
01:33
directly from the crew movies and cast movies pivot tables.
01:37
So we'll be working directly with columns
01:40
as they're defined inside of the table here.
01:42
So this will be our member dot cynist_id,
01:47
as that's what the column is literally called
01:49
within our crew movies pivot table.
01:52
And that'll be in charge of discerning
01:53
whether or not this particular option is selected
01:56
as we loop over our cynist options.
01:58
Our next form input for the individual crew member
02:02
that we're on is going to be a self-closing form input.
02:05
The type's gonna be text, so we can omit that
02:07
with a label of title so that we can discern the title
02:11
of this individual crew member for this particular movie.
02:14
And the name for that will be title as well.
02:16
Additionally, we can add in the default value for this.
02:19
Again, that's gonna come from our member dot,
02:21
and we have a title column directly on that pivot table.
02:24
Lastly, we wanna be able to remove this member
02:27
from the movie.
02:28
So we'll have a button of type button
02:31
so that whenever we click this button,
02:32
it doesn't actually submit our form.
02:34
We'll have an onclick handler.
02:36
In onclick, what we wanna do is reach up
02:38
to the parent of the button that encapsulates
02:40
all of the fields specific to the individual crew member.
02:43
So that would be this div right here,
02:45
which happens to be the direct parent of our button.
02:48
So we can get access to this button element via this,
02:51
reach for its parent element,
02:54
and then remove that parent element,
02:56
thus in turn removing all of the individual fields
02:59
that we have specific to this crew member.
03:01
And the way that we're going to save this on our controller
03:04
is to sync the data.
03:06
So by simply removing it out of our HTML form,
03:08
it's going to serve as a delete
03:10
anytime that we come to update or save our crew members.
03:13
And we can put a little and times character,
03:16
which will be a little X to serve
03:18
as the indicator for that button.
03:20
Okay, so that should do it
03:21
for our field specific to a crew member.
03:24
Now what we need to do is add the ability
03:25
to add an additional crew member to this crew list.
03:29
So underneath this crew list,
03:31
right above our submit or create button,
03:33
we can add in another button of type button.
03:36
Onclick will add a crew member,
03:40
and we'll create that function here momentarily.
03:42
And we can give this a label of add crew member.
03:45
Now this will be a client side function.
03:47
So we'll want to plop this inside of a script tag.
03:50
So we'll add a script tag down at the bottom of our page
03:53
with a function add crew member defined.
03:57
For this function, what we're going to want to do
03:59
is be able to essentially plop one of the contents
04:02
that we're looping over here for our crew members,
04:05
so that we'll be able to select what that new crew member is
04:08
and define their title as well.
04:10
If you're using something like HTML or Unpoly,
04:13
you would be able to reach out to your server
04:15
to get back that HTML to append into your document.
04:17
We're not, so we're going to reapply this exact HTML
04:22
somewhere that we can easily access it
04:23
from our client side script.
04:25
And to make this easily doable,
04:27
we're going to cut out all of that HTML
04:29
that we're looping over and move it into a component.
04:31
So let's scroll on up to,
04:33
we should have components movie here.
04:35
Let's right click that, create a new file.
04:37
This will be our crew member fields
04:40
or something of the sort.
04:42
There's not a very distinct name
04:43
that would be applicable for this
04:45
and paste the contents that we had cut out in.
04:48
These are the fields applicable to one single crew member
04:50
that we're binding into a movie.
04:52
We'll circle back and fill in the names here.
04:54
Oh, I defaulted to filling in the name here.
04:56
We'll circle back and fill in
04:57
both of these names here momentarily,
04:59
because we're going to need to specify them
05:00
in a specific way.
05:02
So let's jump back into our creator edit
05:03
and let's add in our self-closing
05:05
movie.crewmemberfields component.
05:09
Inside of here, we'll need to pass the member in
05:11
as well as the Cinest options that we have
05:15
specifically for the select,
05:17
so that we'll be able to select
05:18
the applicable crew member Cinest record.
05:20
We can give this component here a copy
05:23
and outside of our form, above our script,
05:26
let's go ahead and add in a template tag
05:28
and give this an ID of crew template
05:31
or something of the sort and paste the component inside.
05:35
So now EdgeJS will render our crew member fields
05:38
both inside of this template,
05:40
as well as for each one of our crew members
05:43
already bound into our movie.
05:44
This section here will serve as kind of the default value
05:47
whenever we're editing.
05:48
Any pre-existing crew members will load in here via Edge.
05:51
Otherwise, we'll get a template that we'll be able to clone
05:54
and append in anytime that we click
05:57
our add crew member button.
05:58
Now we have a little bit of more work to do here.
06:01
So first and foremost,
06:02
we're not going to have a member for this one.
06:04
So we'll want to pass it in as null,
06:06
meaning that we need to jump into this component
06:08
and make sure that that is nullable.
06:10
So we can just use optional chaining
06:11
for both references of our member
06:14
to make sure that that is valid.
06:16
Next, we need to take care of the names for both of these.
06:19
Now, there's a number of different ways
06:20
we can go about adding a name in for this
06:22
and square brackets are going to be necessary
06:25
in order for us to send this up as an array
06:28
or even an object.
06:29
So we can give it a baseline name of crew
06:32
and it will send up as such.
06:33
And we can specify that crew is going to be an array
06:36
by adding square brackets to the end of it,
06:38
similar to how you would in TypeScript
06:40
if you have a type that is an array.
06:42
Then we can specify kind of an object key
06:44
specifically for this field
06:46
by doing another bracket pair
06:48
and adding the name of the object property
06:50
that we want this to be applicable to,
06:52
which in this case, ID would probably be good
06:55
as the value is going to be sent as ID.
06:57
We can do something similar down here for our title as well.
07:00
So we'll have crew, add that into an array,
07:03
do another set of brackets
07:05
and give it a property name of title.
07:07
Now I'm pretty sure we're going to have an underlying issue
07:10
with this approach,
07:11
but we'll go ahead and test it out and see how it goes.
07:13
So in order for us to test this out,
07:15
we need to rig up our add crew member button.
07:18
So outside of our add crew member function,
07:19
what would be good is to already have a reference
07:21
to our crew template, as well as our crew list.
07:24
So let's go ahead and query both of those.
07:26
So we could do const crew list equals document.getElementByID
07:31
and pass in the crew list ID there.
07:34
And we could do const crew template equals document.getElementByID
07:39
crew template.
07:41
Within our crew list, what we can do is append child,
07:45
essentially a clone of our crew template.
07:48
So we can take our crew template, reach for the content,
07:51
tell it to clone the node,
07:53
pass in true there to clone it deeply.
07:55
And then this should clone the crew templates contents
07:58
and append that element into our crew list.
08:01
So let's give it a save.
08:02
And then let's jump into our movie validator
08:05
and let's rig this up in a way
08:06
where it's gonna come up invalid,
08:08
just so that we can easily get back
08:09
and see exactly what it is that we're posting up.
08:12
So let's do crew and let's say vine date.
08:16
We're certainly not gonna be posting a date up
08:18
for our crew.
08:19
So that should most certainly fail.
08:21
And then on our creator edit,
08:22
let's go and scroll up to the top
08:24
and let's plop an instance of our flash messages.
08:26
So let's inspect it out, flash messages,
08:29
and we can reach for all of them
08:31
just so that we can easily see exactly what it is
08:33
that we're posting up here
08:34
as we submit and test out our crew list functionality.
08:38
Okay, so we don't need to do anything
08:39
in our movies controller yet
08:40
because our validator should prevent us from getting there.
08:43
And it looks like we have an error,
08:45
cannot read Sinus ID.
08:46
I'm gonna go ahead and refresh that
08:47
to see if that was, okay, yep.
08:49
That was just something we saved along the way
08:50
with an invalid state.
08:51
So we are good to go now.
08:53
If we hit add crew member, look at that,
08:55
we get our crew member field.
08:57
We have our crew member selects.
08:58
So we could select somebody there,
09:00
type in some title, and we can also clear them out.
09:03
So if we added another one, but we only wanted one,
09:05
we can clear that out.
09:06
Let's start by trying to update our movie.
09:08
Okay, you can see our validation most certainly failed
09:11
and you can see that we're getting back crew ID
09:13
with a value of 33 and a title of some title.
09:16
So this is sending up as an object rather than an array.
09:20
However, if we come back down here
09:22
and we add in two crew members,
09:25
and let's make sure that they're a little bit different,
09:27
and let's go ahead and post again,
09:29
you'll see that now crew is still an object,
09:31
but ID and title is now an array of values
09:36
where it was previously just a string.
09:38
And I'm going to double check myself
09:40
to make sure I'm remembering that correctly as well.
09:42
So if we post that back up, you can see,
09:44
yep, most definitely just a string.
09:46
So what we kind of need to do
09:48
is normalize its expectations a little bit
09:51
by specifying an index of our array
09:54
that we want the items to be members of.
09:56
So if we hide this back away,
09:58
within our crew members fields,
10:00
if we specify now an index within here,
10:04
so we'll switch these two back ticks,
10:06
both of them right down here,
10:08
and inject in an index,
10:11
which will provide as a prop to this component.
10:13
So an index just like so, give that a save,
10:16
jump back out to our creator edit,
10:18
and then we'll need to grab the index out of our loop there,
10:22
pass an index in here,
10:23
and we're not going to have a specific index
10:26
to be able to patch in here.
10:27
So that's where things get a little tricky on this front.
10:30
Instead, we want to do index
10:32
with some sort of placeholder that we can replace.
10:34
So maybe a capitalized index string.
10:36
And then instead of directly cloning the node
10:39
and impending it directly in,
10:41
we're instead going to want to get the HTML of the template.
10:44
So rather than cloning it as we were before,
10:47
reaching for the content,
10:48
we'll want to instead just do crew template inner HTML.
10:52
And this will allow us to easily replace
10:55
all instances of that index placeholder
10:58
that we added into that component
11:00
with the const next index,
11:04
which is our crew list children length.
11:08
Because instead of our crew list,
11:09
we have one child div per crew member that we're adding in.
11:13
So that's going to equate to the next index
11:16
that we want to append into that list.
11:18
So we can pass that in here, next index, just like so.
11:22
Then in order for us to be able to append the child in,
11:24
we're going to need a node.
11:25
We could do inner HTML and append in that way,
11:28
but that's going to re-render the entire DOM,
11:31
which would get rid of any adjustments
11:33
that we had previously made to this section of our form.
11:35
So we do want to use append child here.
11:38
So we can do const temp and create a new element.
11:43
We just patch that as a div,
11:44
and then we can do temp inner HTML equals our HTML,
11:49
and then reach for that temp.firstElementChild, like so.
11:54
So now if we give this a save,
11:55
we jump back into our browser.
11:57
Let's start by adding a single crew member in
11:59
and see how this posts.
12:00
So let's select somebody there,
12:02
some title there, update our movie,
12:05
and you can see exactly how that switched things up.
12:07
So rather than doing crew as an object
12:10
with individual ID and title properties
12:13
with either a string or array there,
12:15
it's now crew is an array,
12:17
and we have a single object with ID and title
12:20
as properties inside of there.
12:22
So if we add two in now,
12:24
so let's add that twice, add crew member, add crew member,
12:27
select some random people here,
12:28
and give them some title one and some title two,
12:33
update our movie again,
12:34
you'll see that we still get back an array,
12:36
but now we have two different objects inside of our array
12:39
with some title one and some title two.
12:41
This is really ideal for how we're gonna want to
12:44
patch it up on our server side inside of our controller.
12:47
So we'll want to keep forward
12:49
with this particular syntax here,
12:51
but there is a downside that we'll need to account for
12:53
later on here as well.
12:55
But for now, let's go ahead and get this saving.
12:57
So let's first jump into our movie validator
12:59
and update our validator to accept in
13:01
exactly as we're posting it.
13:02
So we're gonna have a vine array,
13:05
and we're gonna wanna make sure that that array is optional
13:07
because we may not have any crew members being sent up.
13:09
Inside of our array,
13:10
we're gonna want this to be a vine object,
13:12
so an array of objects,
13:14
and for those objects,
13:15
we're gonna have an ID of type vine number,
13:18
and we can even do an is exist check,
13:21
making sure that the table of our sinists
13:24
and the column ID contains the value
13:27
that we're sending up here,
13:28
and then title vine string for the crew members title.
13:33
Give that a safer formatting,
13:34
and this should now match the syntax
13:36
with how we're posting it up.
13:37
So let's jump into our movies controller next
13:39
and get it added.
13:40
So we have the additional field within our validator of crew
13:44
which contains our crew members,
13:46
and what we're gonna wanna do is get back an object
13:50
where the key is the ID and the object is the ID's title,
13:55
and it also has a sort order for them as well.
14:00
So we're gonna want this format.
14:02
So if we have multiple, it would be like ID two,
14:04
so on and so forth, looking like that.
14:07
So we can use reduce to easily build that object.
14:10
So const crew members equals crew reduce,
14:15
and that's going to be optional.
14:16
We'll have our accumulator object, our row,
14:20
and an index so that we can add in the sort.
14:22
Our accumulator is going to start out as an empty object,
14:26
and for each time that we're looping over it,
14:28
we're going to take that accumulator
14:30
and add in the rows ID with an object of title,
14:35
row.title, and sort_order,
14:39
because remember we need to post this in
14:41
as is defined in the database
14:42
since we don't have a model defining this pivot table,
14:45
and the index will serve as our sort order there.
14:48
Then of course, we'll need to return back
14:50
that accumulator for the next loop.
14:52
Now we're gonna have some red squigglies
14:54
because we haven't defined a type for this.
14:56
So we'll need to type hint this reduce as well,
14:59
and we can type hint this as a record
15:02
where the key is a number,
15:04
and the value is an object with title, string,
15:08
sort, order, number, just like so.
15:11
And we need an extra caret there at the end of that.
15:14
Give that a save so it should format
15:15
and get rid of all of our squigglies.
15:17
It looks good.
15:18
And now all we need to do is await,
15:20
take the movie,
15:21
reach for the relationship of our crew members,
15:24
and we'll want to use sync
15:25
because our crew members here is the source of truth.
15:28
If we've removed somebody from the crew members
15:30
and we want to delete them,
15:31
and anyone that we add in, we want to append in.
15:34
So sync will take care of both of those use cases in one go,
15:37
and just use our crew members here
15:39
as the source of truth for who the crew members are.
15:42
And of course, this is optional,
15:45
so it may not have a value at all.
15:47
So we can default that to an empty array
15:50
if we didn't provide anybody in.
15:52
Okay, so this should get us to where we can
15:54
at least save some people in,
15:56
and then we'll take a look at the next issue.
15:58
So let's add some crew members,
16:00
take a look and add Camille in,
16:02
maybe they got the food,
16:04
and then we'll do Leela,
16:06
maybe they did the hair for the movie.
16:08
We can go ahead and update our movie,
16:10
and now you can see we got redirected right back
16:12
to our movies pagination page,
16:14
and we can see for this movie,
16:15
we have a crew members of two now instead of zero.
16:19
Go back in the edit,
16:20
we're not gonna see them yet
16:21
because we haven't added it into the query,
16:22
so let's do that next.
16:23
Jump up to our update,
16:25
we'll worry about creation here
16:27
after we get all of our issues resolved,
16:29
and we're going to want to query this as mentioned earlier,
16:31
directly from our pivot table.
16:33
So const crew members equals await,
16:36
we can reach for the database module to do this,
16:39
from crew movies, which is the name of the pivot table,
16:43
where that movie ID equals movie.id,
16:47
and again, know that we're using the table and column names
16:50
as we define this out of the database
16:51
because we're using the database module,
16:53
which does not go through our Lucid models.
16:55
And then lastly, we want to order by the sort order field,
17:00
give that a safer formatting,
17:02
and edit into our page states,
17:03
so crew members there.
17:05
All right, now if we jump back into our browser,
17:07
we should now see both of our crew members,
17:09
we'll give it a refresh, there they are.
17:10
So all looks good, right?
17:12
We can add in an additional crew member and it should work.
17:16
So let's add Natasha, maybe she did makeup,
17:19
update our movie, and sure enough,
17:20
added in A-OK, we should now have three, which we do.
17:23
The issue comes in though, with these indexes
17:27
that we are defining on these elements.
17:29
So we have crew zero ID, as we remove these items,
17:33
this index is not going to auto update
17:35
because we're not touching those elements in any way
17:38
whenever we make that removement.
17:40
So if we take a look at the first item now,
17:41
its first index is one.
17:43
Why is this an issue?
17:45
Well, let's go ahead and try to update our movie
17:47
and we'll see.
17:47
So let's take a look at our flash message.
17:49
The value that we're now posting up is crew with an array,
17:53
and the first index which we removed is now null,
17:56
because there was no representation
17:58
for the first index of this array.
18:01
What we could do, so let's go into alpinejs.dev,
18:05
and I'm just gonna go ahead and copy their script
18:08
right there from the CDN.
18:10
If you want to, you can go into your script
18:11
and fully install it,
18:13
but we're just going to want it on this one individual page.
18:16
So we'll plop it in just before our script here.
18:18
Believe it or not,
18:19
this is actually going to drastically simplify what we have.
18:22
So we can get rid of our template
18:24
as well as our script here as a whole too.
18:26
So we go ahead and remove that, scroll on up,
18:29
and rather than doing an ID crew list,
18:31
what we can do instead is x-data,
18:34
define the state of say our members as,
18:38
and we can use EdgeJS's interpolation
18:41
to now stringify our crew members
18:45
and pass it directly into the members variable
18:47
on the client side via alpinejs.
18:50
AlpineJS is like a very lightweight version
18:53
of Vue or React.
18:55
It's going to sprinkle in client side JavaScript
18:58
DOM manipulation for us
19:00
so that we can easily perform re-renders
19:02
of our inner child content as it updates.
19:06
This is going to make swapping out that index
19:08
as we remove items super easy,
19:10
and it's going to eliminate the issues
19:12
that we've seen thus far.
19:13
This stringifies a JavaScript helper.
19:15
Actually, I believe it's js-stringify.
19:17
It used to just be stringify in version five
19:20
and advanced js6,
19:21
they've now namespaced it underneath js.
19:23
This will take what we pass in
19:24
and safely stringify it so that we can easily pass it in
19:27
as a value here in our attribute.
19:29
This x-data is how we define state for Alpine
19:32
similar to again, Vue or React state.
19:35
And that's going to make sure that we have access
19:36
to members inside of this div right here,
19:40
essentially serving as kind of a micro component
19:43
for AlpineJS.
19:44
Meaning that we can actually dive back
19:46
into our crew member fields component.
19:49
And if we wanted to, we could reapply all of this
19:51
just right back out inside of AlpineJS.
19:55
And since we have all of our members,
19:56
we can loop over it using Alpine
19:58
and get rid of our EdgeJS loop there as well.
20:01
We'll want to add in a template,
20:04
which is what EdgeJS uses for loops,
20:05
do x for member in members,
20:09
add in a key of member.id,
20:13
and in that template,
20:14
we can go ahead and cut that out
20:15
and paste it down at the bottom of our div here,
20:19
scroll up a little bit and give ourselves an indent.
20:21
So next what we need to do is move the name from EdgeJS
20:24
now to our client side via AlpineJS
20:27
because Alpine now contains who our members are
20:30
rather than our EdgeJS loop.
20:33
Now, so that we're not spending a ton of time
20:35
mutating our forms so that they support AlpineJS,
20:38
that's certainly doable.
20:40
Instead, what we're going to do is just swap these
20:42
from using EdgeJS to Alpine.
20:44
So let's go and jump into our form
20:46
and select our span here
20:48
just to make sure that we're using the same styling.
20:50
And we have a label class flex flex call,
20:54
and then we have that span with our crew member label.
20:58
And then we have a select with the name
21:02
and then our options.
21:04
So we can cut out our EdgeJS loop with those options
21:07
and paste it in here.
21:09
The name is now going to be an interpolation from AlpineJS
21:13
and we'll do double curly braces there
21:14
so that we can inject
21:16
and we'll want the index out of the loop.
21:18
And then we can do crew, inject that index
21:21
and say that this is the ID field.
21:23
So now every time AlpineJS loops over this to update it,
21:27
it will inject the correct index
21:29
based off of the loop index,
21:31
fixing our issue that we were running into.
21:33
Now we are doing our selected check in EdgeJS still,
21:37
but we need to switch this to Alpine
21:38
because member is now in our client side via Alpine.
21:42
So we can use interpolated selected here
21:45
to say if member.sinist_id equals,
21:50
and we can use EdgeJS to interpolate in
21:53
who this current sinist.id is.
21:56
So a nice blending of client side
21:58
and server side code here going on.
22:00
Server side being our EdgeJS interpolations
22:03
and client side being our AlpineJS interpolations here.
22:05
Scroll down here, we'll take care of our input next.
22:08
Let's select the label that we have going on,
22:10
paste it in, do input type text, name,
22:15
and then do our interpolated name here,
22:17
backticks, crew, inject in the index,
22:21
and then add in that this is the title field.
22:23
And then for the model, this would be an X model.
22:26
And I think for AlpineJS,
22:28
you need to do members, reach for the index.title.
22:31
Similar to how view two was.
22:33
And end that up.
22:34
We can actually switch our select to do that as well,
22:37
thinking about it.
22:38
So we could scroll up,
22:39
let's end our label before we do that.
22:40
So end our label there.
22:41
Now let's scroll up,
22:43
and rather than doing our selected,
22:45
we can do X model, members, index, and reach for the ID,
22:50
which means that we can get rid of this
22:51
on our option altogether.
22:53
Scroll down a little bit further
22:54
because this is no longer just going to remove the element,
22:57
but rather remove the item out of our members array.
22:59
And we'll need to switch this to an at click now.
23:02
And we can do members equals members.filter,
23:06
item or item.id does not equal member.id.
23:11
And then for our ad crew members,
23:14
what we'll want to do is instead members push,
23:18
we can do an ID and reach for EdgeJS's
23:22
since the first option.id there to plop that in
23:27
and title as just an empty string,
23:29
directly mutating the state that we have up here
23:32
in our x-data.
23:33
You could also define this method directly in x-data
23:35
and call it from our button to there as well.
23:38
So let's give that a save,
23:39
jump back into our browser and okay,
23:41
it looks like everything's still working.
23:42
Let's do a sanity check refresh.
23:44
Cool.
23:45
Let's try to update our movie real quick
23:46
just to make sure everything goes.
23:47
And it looks like it did not get our titles.
23:50
Okay, scroll back down, right click the field,
23:53
inspect, and it looks like I messed up the index
23:57
there a little bit.
23:58
Let's hide our browser back away
23:59
and see if we can fix that.
24:00
Scroll on down to where we have that title.
24:02
And sure enough, I put a square bracket in.
24:04
Get rid of that.
24:05
Try that one more time.
24:06
So let's jump back up into our browser,
24:07
refresh for sanity sake, try to update it and cool.
24:10
Okay, so it went okay, but we only now have one person.
24:13
That's not right.
24:14
Okay, so I rewrote this whole thing
24:16
for the crew members here three times
24:17
just to see that I had a very small issue
24:20
that was preventing our ad crew members button from working
24:22
and it caused a few other issues.
24:24
So let's go ahead and hide our browser back away
24:26
before we test this out.
24:28
And the issue was that the ad crew members button
24:31
is outside the realms of our x-data.
24:34
So it doesn't know or have access to that state
24:37
because it's not encapsulated by it.
24:39
So what we wanna do is cut that state out of this div,
24:42
wrap it in another div,
24:44
since this div in particular is for listing out
24:47
each one of our members, it has that flex flex call on it.
24:50
So we don't want that to be on there,
24:52
but instead on a parent div,
24:54
and then we can indent everything up through our button
24:59
and encapsulate our button now
25:01
in that extra div that we have.
25:03
So now if we collapse down our template,
25:06
our x-data and the div containing it
25:08
is now including our button.
25:11
Additionally, I'm not sure if I had this initially or not,
25:13
but we also wanted the selects X model
25:16
to reference the members index Cynist ID
25:20
rather than just the ID.
25:22
That might've been another issue that I had
25:24
that was causing some strangeness.
25:25
So with both of those in place,
25:27
we should now have a working system
25:29
without the oddities that we've seen in the past,
25:33
where we'll have a differentiation in our post behavior,
25:36
depending on the number of items that we have being posted.
25:38
So for example, if we post up here
25:40
with Quincy Abernathy as test two,
25:42
Jermaine R as test three,
25:44
and we maybe add in somebody else here as test four,
25:47
Natasha, test four, updates.
25:50
There we go.
25:51
We see that we get crew members of three.
25:53
If we go back in the edit and we remove two,
25:56
which was one of the issues that we had solved
25:57
because now this would be index one
25:59
and this would be index two.
26:01
AlpineJS should fix that for us.
26:03
Automatically now making this index zero
26:05
since we've removed the original zero
26:07
and now this index one.
26:09
So let's try to update and sure enough, it worked.
26:11
Awesome.
26:12
So now we have two crew members
26:14
and if we take this now down to one,
26:16
so let's run through that again.
26:17
Leave just Natasha, update once more.
26:20
Awesome.
26:21
Now we just have one.
26:22
So everything there is now working a-OK.
Join The Discussion! (2 Comments)
Please sign in or sign up for free to join in on the dicussion.
drummersi-3
Great lessons, but I had real trouble on this one. I'm new to AlpineJS but trying to add the same crew member twice completely broke it, with more issues when trying to "sync" on the backend.
In the end, I changed the alpine key to use index instead of cineasts_id, then in Adonis removed the 'sync' method and simply deleted all crew_movies entries and mass inserted the new entries
Please sign in or sign up for free to reply
tomgobich
Terribly sorry about that drummersi-3! This module wasn't originally a part of this series, I added it on last minute and that really shows in this lesson! I'll have to re-watch this module and think through how to appropriately correct it. Again - apologies you had difficulty here, there's definitely room for improvement on this lesson.
Please sign in or sign up for free to reply