So in this lecture,
we will finish implementing the bookmarking functionality.
And remember that basically the only thing
that is still missing
is that when we bookmark a recipe like this,
then we want that recipe to show up here
in the bookmarks panel.
So right now that is still empty
and we only see this friendly message here.
And so let's now go fix that.
So taking a look at or mark up here,
we can see right here,
so we can see that in the bookmarks,
we will actually have also the preview element.
So this one here,
so basically a list element
with the class of preview in it,
just like we had here for the search results.
And so this is actually the exact same code.
And so now in order to create this bookmarks view,
I can actually simply go ahead
and copy this one here from the results.
Okay.
So at least for now,
by the end of this video we will then kind
of refactor all this,
but for now let me simply copy the code here.
And here create the bookmarksView.js.
And then here of course,
it is called BookmarksView.
Okay.
Then we also need to change the parent element,
which in this case will be
this unordered list called Bookmarks_List,
right here and here.
The error message should be no bookmarks yet,
find a nice recipe and bookmark it.
All right.
But the rest of the code here
is actually going to be the same.
And so let's now go here.
This one we can close.
That's no good to the controller
and include that here.
And let's actually do that below this one,
just because it is so similar.
So results and bookmarks
or actually let's do it here at the end,
so that results and pagination stay together.
And so now all we want to do
at least for now is that whenever a new bookmark is added,
we want to render the bookmarks view
with all the bookmarks.
So with the array of bookmarks.
So is right here in controlAddBookmarks ,
delete all these console.logs
and as always add some comments.
So add or remove a bookmark,
then here,
update recipe view.
And then here actually render to bookmarks.
So that is bookmarksView.render
and see how beautiful,
and now everything comes together
or basically fits together.
So we always have this render method
and we already know that we can call it on all the views.
And so that's really nice about having an architecture,
a structure like this.
So that's going to be model.state.bookmarks.
And so this is also the reason why,
why in the state we didn't only store
the IDs of the bookmarks,
but really we stored the entire data about the bookmarks.
So that we can nicely display them in this list.
So a list that will look exactly like
the result list here.
So this should now actually already be working.
So let's click this one here now,
edit as a bookmark.
And now when we come here,
done there it is.
Great.
So let's try another one.
And or bookmark here is still there.
Now, if we add another one,
done.
Now we have two of them.
And you can see that it also already
automatically highlights the current recipe.
So the one we are currently seeing,
so if we now go to this one again.
well, 10 the spicy chicken
should actually be the selected one here.
And so apparently we still have some kind of bug.
So basically what we have to do here
is that each time that we display a recipe.
We should probably update this entire
bookmarks panel here.
So this view so that it can then basically
select or highlight here the current recipe.
So let's do that in the control recipe function,
and you see that this one here is getting really crowded.
So let's do that here.
So bookmarksView.update and then again,
model.state.bookmarks.
Okay.
So let's add this one.
Okay, that worked nicely.
And now this one here became the current one,
but now let's go to some other one,
which is not any of the bookmarks.
And so now none of them you see here is selected.
And so of course,
that makes sense because while this is not one
of the bookmarks.
But now if we click here,
then this one is of course the selected one.
Now we can click here as well.
Because again,
these elements here are basically just
the same as these ones.
So when we click here,
it loads the corresponding recipe
and here are the same.
So you see that now we went back to this one
and this one got selected correctly.
This one got selected correctly as well.
And we also got the correct recipe
and that's just amazing.
So you'll see how easy it is now
to integrate a new feature like this bookmark feature.
When we already have a very nice architecture
and structure in our code.
Imagine that we had all of this code here,
simply in one huge messy file.
Then how difficult would it be to keep track
of all the data and of how these different
functions all interact with one another.
Now, just to finish we need to fix the fact
that these two views here are essentially the same.
So at least the markup that they generate
is in fact exactly the same.
And so that is of course not good.
So what I will do now is to basically implement
a view that is kind of a parent view
of these two views,
and that will be called the previewView.
So because this element here is called preview.
And so then that can contain all of these methods here.
And then in the generate markup of these two,
we will then use those two.
So but instead of explaining it,
let me actually show it.
So that's a previewView.js.
And now let me get all of this here.
All right.
So this will now be called PreviewView.
And what this view will do
is to basically only generate
one preview element like this here.
All right.
So this one will not have any message.
It will not have an error message.
And the parent element is also not important.
So just follow me here for now.
And I will explain why that is.
So here I will simply select everything.
Or in fact I could simply set this here to an empty string.
So we don't need any parent element here.
And actually this year is only the generate markup
and here we don't need any of this.
Okay.
So again,
this preview view will only generate the markup
for one of these preview elements.
All right.
So now let's come here to the bookmarksView
and get rid of this method here,
so that we don't need anymore.
And now here comes the magic.
So as I mentioned before,
we will use the previewView kind of as a child view
of the bookmarksView and of the resultsView.
So let's import the previewView here.
So import previewView
from .js
and now what we will do here
is to still loop over this.data,
which is still all of the bookmarks.
But now what we want to do here
is to call basically this generate markup.
However, that would not really work.
And so what we really want is this.
So result,
and then for each of them,
we want preview.render,
actually.
So with the result,
but actually that is not all yet
because like this wouldn't work.
But let's quickly analyze what is going to happen here.
So these three here,
so as the render method on bookmarksView is called,
so this render method,
it will set the data on the bookmarksView
and then it will generate the markup.
So it will call this method here.
And so this gets access to this.data,
and then we map over that data.
And so for each of the results,
or let's actually call it bookmarks here.
So bookmark.
So for each of this bookmark,
so not the boom mark.
So for each of the bookmarks,
we want to then render a preview.
However, here we actually need to return a string.
So all of this should be a string
that we need to return from the generate markup method.
So that then in the view,
it can insert that markup into the dam.
Right.
However, by having render here,
preview.js itself we'll try to render some markup.
And so that is not really going to work.
And so what we will do is to change
or render method here
and add a second parameter to it.
So here we will add a parameter called render,
which by default will be set to true.
So then all of this here stays the same,
but if render is false,
which is what we will set it to in a minute.
So if render is false,
then we actually want to return
this markup that was just generated.
Now, why don't we simply call generate markup
itself without messing with the whole render method.
So here,
why don't we simply call previewView.generate markup?
Well, that's because we still
need it to set the data property
to the data that we passed in.
So that then here in the previewView,
we can use this keyword.
And so actually we need to now replace result by this.data.
So this.data and then all of that.
Okay.
And so here we want to render it
and set the render parameter to false.
Okay.
So that was a lot to take in.
So let's recap what happens here.
So the first part I think is obvious.
So what happens when bookmarksView.render is called?
So we then enter this method here.
Now, since we didn't duplicate the same code here
of previewView.
So basically this way here of generating this preview,
we essentially separated that into its own child view.
And so then here in the bookmarksView,
we try to render basically that view
for each of the bookmarks,
but instead of actually rendering it to the dam.
We simply have to render method returned
to markup as a string.
So that's why we set it here to faults,
which will then trigger this code here.
Right.
And so then all of this year will basically become a string.
And so in the end,
we end up with an array of strings.
So because of map,
and then in the end we join all of that together
and end up with a big string
with all the markup that we want to render.
So let's see what happens here.
So as we click,
let's see the console here
and it looks like we didn't get any error.
And so indeed now here or bookmarks still work.
Now the search here will not yet work
because we still need to put this here
in the results view.
But that's very easy.
All we have to do now is to copy this code
and put it here,
and here we can now call this result.
But of course it would have worked exactly the same way.
And we also need to import the previewView,
but that should be it.
And so now these two views are essentially the same thing,
but the only difference that they have a different
parent element and a different error message.
Right.
But the main functionality of them.
So the main way of generating the markup
is essentially the same for them.
And so in order to encapsulate that somewhere,
we created another child class.
And so that is again,
this one here.
Okay.
So please analyze this here.
After this video is done
and really take a look at how the data
flows between these different modules
and between these different classes.
All right.
So let's see.
And indeed it still works.
So here for now we get no message
because we don't have any bookmarks yet,
but as we click it,
then that should appear there.
Let's add another one and beautiful.
So that works great.
Here we can then come back to the next one
and now let's un-bookmark it.
So it should disappear now
and now un-bookmark this one as well.
And then we get automatically this message here.
So the no bookmarks yet message,
which of course automatically comes
here from this error message that we specified
in this bookmarks view.
So that's really great.
So our application
is becoming almost finished actually,
and now all that we want to do here
to finish the bookmarks is to actually persist it
and between page loads.
So right now, of course,
this one here is bookmarked,
but now as we reload the page,
then that bookmark is gone.
Right.
So it's no longer here
and it's also no longer up here.
And so now what we're gonna do next
is to store or bookmarks data into the local storage.
And then as we load the page,
we basically get that data back.