Narrator: Welcome back to the next part of the app,
which is the shopping list.
And in this video, we will build our data model
where you will learn how and why
to create unique IDs using an external third party package.
You will learn or remember the difference
between the slice and the splice methods on the array.
And also, we will see some more use cases
for the find index and find methods also for the arrays.
So, let's get to it.
So, as always, the first step is to create a new file
in the models folder, so List.js.
Okay, and once more, we want to represent
the shopping list through an object.
And so, once again, we build a class here
which we used as a blueprint of course
to then generate the list object, later in the controller.
So, let's export
default, of course, a class
called List.
Then the constructor.
And this time around, we're not going to
pass anything into the constructor.
So, basically, when we initialize a new list,
we don't need to pass anything.
All we want to do is to say
that we have an items property set to an empty array, okay?
So, this.items
is an empty array.
And so, when we start adding new elements to the list,
they will all be pushed into this items array, okay?
So, basically, all of the elements in our list
will all be stored in this one property, this.items.
Alright, so let's now create the method
to add a new item to the list.
So, we need to pass in the count,
the unit, and the ingredient.
Because our list is, of course,
a list of ingredient, and it has the same structure
as we have the ingredient data, okay?
So, remember we always have a count,
a unit, and an ingredient.
And so that's exactly what we're going to add
to the list as well, okay?
So, basically, we will have an array
in which each of the elements is an object,
which will have the count, the unit, and the ingredient.
Alright, so let's actually create an item here,
item.
And it will have the count property.
Remember that we don't actually have
to specify it like this, because it's just the same name.
In ES6, that's not necessary.
And same goes for unit, and the same goes for ingredient.
Now, there's just one thing missing here,
which is an unique ID.
So, we need each of the items to have an ID,
so that we can later identify them when we want to
update their count, or when we want to delete them
from the model and from the user interface.
So, we gotta have a unique identifier
for each of these items.
And we did something very similar in the budgeting app.
Remember that?
And back there, we simply specified a number
and said that whenever we added a new item,
the next one should have the next number as an ID.
So, the first one had 0, the second had ID 1, 2, 3
and so on, until fourth.
That thing created some problems when we deleted some items,
then we had to go figure out
the next ID that we should use. Remember that?
And so this time around,
we're gonna do it in a different way.
So we're gonna include a small library,
which will create unique IDs for us, okay?
So let me show that package to you.
I already have it opened here.
It is called Uniqid, here on Github.
It is very simple.
Always create unique IDs based on
the current time process and machine name.
And all we have to do is, really,
use the unique function and it will return us a unique ID.
Let's now install this package here,
and save it to our package adjacent file.
And we can wait for it, and while it does its installation,
we can already start including it here.
So let's import uniqueid
from uniqid.
This one here is not correct, unique,
It's just really like this weird way of spelling it.
So, uniqid from uniqid and so, let's add the ID property.
On ID we want to have uniqid. And that's it.
So this will create a unique identifier
for each of the items, based on the small library.
Just take a look if it already installed.
And indeed, here it is. Uniqid on version 4.1.1.
Alright, next up we want the ability to delete an item.
And so now, we need these IDs, okay?
So, what we're gonna pass into delete item function,
is just the ID of the item we want to delete,
which we will probably get from the user interface,
and then based on that ID, we are going
to delete the item from our items array.
So, how are we going to do this?
Well, we will use the splice method.
So on this.items, we will use the splice method.
And now what does the splice method do?
Well, basically, we pass in a start index
and then how many positions we want to take.
And it will then return these elements
and delete them from the original array. Okay?
So it mutates, actually, the original one.
And this one is a bit similar to another one, which is slice
So, slice is very similar to splice,
with the difference that
slice accepts a start and an end index
of the portion that we want to take
and the returns a new array.
And also, it doesn't mutate the original array. Okay?
So for example, imagine that we have this array,
2, 4, and 8, okay?
So let's add a comment here.
So, if we say splice,
1 and then 1, it will start at position number 1
and take one element, so only this 4.
And it will then return 4 and mutate the original array.
So return four and the original array is:
2 and 8. Okay?
So that's what happens with the splice.
And if we say slice, which is the same,
then it will start on 1 and end on 1.
So, it will still return 4 and the entire array will be
the entire array from the beginning
because we do not mutate the original array.
But the difference here is that
this one is the end-index while in splice,
this number here means how many elements we want to take.
So if we said 1 and 2 here, well then it would take
4 and 8,
returns 4 and 8,
and the original array would only be with number 2,
and if we add 2 here,
well then it would actually return the 4
like we have it here.
Because remember, this second tier is the end
but it's not included.
So, actually, if we had 1, 1, then it would return nothing.
Because it would start in 1 and end on number 1,
and so it wouldn't return anything.
And only when we say 1, 2,
so start at position number one
and end on position number two
well then it would return the 4
and of course, not mutate the original array.
Now what we have to do here is to find the index
at which we want to splice.
So basically, what we want is, based on the passed in ID,
we want to find the position
of the item that matches this ID.
So let's start by doing that.
So, const index
and we will use, this.items.findindex.
Okay? We have already used this one here before;
it's a very handy method for doing this kind of stuff.
We have a a codec function
which receives the current element and all we have
to do now is to test if the current element.id equals
the passed in ID.
It will now find the index
of the element which satisfies this condition.
So where the element ID is equal to the ID to be passed in.
With this, we got the index where
that exact item is located, and so all we have
to do now is to say index, and 1,
because we only want to remove one element.
We start at the position where the item is located,
and then take out one element.
Alright, and that's it already.
Because this mutates the original array
and so, it will really take out, it will delete,
this element from our original items array.
Now we also could now return the deleted item.
All we have to do would really be return
And so this will now return the deleted item,
but we don't want to do that.
All we really want to do is just delete the item.
Once more, we use the very-handy find index method.
The last one is that we want to update the count.
So, we are not really going to update the entire element,
but we will simply allow it to update the count.
We will pass in the ID of the element
that we want to manipulate and also the new count.
And let me quickly show it to you in the user-interface.
In the final app.
It's this one.
So we have these buttons here where we can update the amount
of the ingredient, but not the unit, of course,
and also, not the ingredient itself.
So all we can really change here is the count.
That's why we're having this update count
where we are passing the ID
and the new count that we want to save in the object.
And this one is actually, even easier
to implement the one before.
Let's say this.items,
And so what we want to do now is, not to find the index,
but to really find the element itself.
We can do that by using find.
So, yet another ES6 method which is a bit similar
to find index here, but instead of returning the index,
it will return the element itself.
The rest is really the same as up there.
We want to find the element which has,
as an element ID the one that we pass in, okay?
This will return our item.
Then we can say that we want to count of that item
to be equal to the new count.
And that's it.
So with one line of code, we achieved this functionality,
which, without ES6,
would have been a bit more complicated to implement.
I hope this makes sense here.
This part, which is maybe the most tricky part,
but I hope it still made sense to you.
Again, what we do here is basically to loop
through all the elements in the items
and then select the one that has the ID equal
to the ID that we passed into the function.
Then we return that object
and change the count property on it.
Let's now go into our controller and include this,
so, import this, basically.
Recipe and change them both to list.
And, just like before, let's actually create a new element.
A new list element.
Just to test it out in the console.
Const l is a new list that will then attach this list
to the global window object such as we did before.
And, actually, we could simply do it like this.
Window.l is simply the new list.
Now, we are going to be able to use all
of the these methods here that we just created.
Let's try that.
Now we have all these console unlocks here,
so let's get rid of that actually.
We don't need that.
It's actually this data recipe.
I guess.
Probably it's not, but we also don't really need that one.
What we really want here is this. State.recipe.ingredients.
Let's wait for it
And now, we should be able to access l,
which is, of course, an empty array, at this point.
Let's use addItem here,
and remember what we need to pass in starts with the count.
So, the count the unit and the ingredient.
And, of course, the ID will be figured out automatically.
Let's say, we need to pass in two tablespoons
of salt, for example.
Let's add another one.
Two tomatoes.
And you see it didnt edit to the list really.
so let's take a look at that.
So we simply created the item here,
but we still have to push it to the array.
That's a stupid mistake.
But no problem of course.
So all we have to do is this.items.push the item,
Variable that we just created.
It's also a good practice
to return the newly created object here.
So return the item.
Alright.
Let's try that again.
Two tablespoon of salt.
And, you see it already returns the new object.
It's working now.
And you see, this is the uniqid
that was created by the uniq package.
So, let's add the other one, the two tomatoes,
and you see it has a different ID of course.
So, it's really working.
So let's now delete the first one here,
and so we need to pass in the ID, remember?
So, l.deleteItem,
and we need to pass in the ID.
Let's take a look at l now,
and now we're only left with one array
which would be the one with the two tomatoes.
So let's take a look at that,
and, indeed, we have the two tomatoes.
So great. That's working.
Now, just as a last step,
let's try to use the update count method.
So, l.updateCount,
we need to pass in the ID once again,
and now we want 10 tomatoes.
Take a look again at l,
and indeed, we have now 10 tomatoes.
So our API is working, and notice how I said API here.
Of course, I'm not talking about the API that we used
to get the recipes.
API is just a term that we can use
also for this kind of stuff.
So we just basically created an API
for creating and updating lists.
So we just tested this API
and everything is working correctly.
In the next video we're going to implement the view
for the list before creating finally the controller.