Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranรฎ)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
1 1
Well, welcome back. 2
2
And I hope that you're still having fun in this project. 3
3
Now, the next part of this project 4
4
is going to be implementing bookmarks. 5
5
And so that's what we will do 6
6
in this lecture and the next one. 7
7
Okay. 8
8
And let's start again with a look at our flow chart here. 9
9
And so in this video 10
10
what we will do is simply basically adding a handler 11
11
to the recipe so that then the user can bookmark the recipe 12
12
and then a that will render or update the recipe 13
13
with the bookmark button, then update it. 14
14
And for doing that there's actually a lot of stuff 15
15
that we need to implement. 16
16
So there's a lot of work for us to do, so let's get started. 17
17
And actually, before we get started 18
18
I think we should actually also see this in action. 19
19
So here in the demo version, so let's say that we are here 20
20
on this first recipe and when I click this recipe 21
21
I then want this, icon here to change right? 22
22
And so this is now bookmarked. 23
23
So when I then go to the next result 24
24
then of course this bookmark here is back to being empty. 25
25
But when I go back to that recipe that I had bookmarked, 26
26
then it is back to being filled. 27
27
And so this means 28
28
that the current recipe is indeed a bookmark. 29
29
Then in the next lecture, we will take care 30
30
of also displaying all the bookmarks up here. 31
31
All right, but that's something different. 32
32
And so for now, let's take care of the core functionality 33
33
of being able to bookmark a recipe. 34
34
Okay and finally there's one more thing 35
35
that we actually need to do before starting that. 36
36
So I discovered a small bug here. 37
37
Let's say that we searched for something. 38
38
And then we go to page two or page three, for example 39
39
and then let's say we search for something else. 40
40
So that gives us our results. 41
41
But as we go back here 42
42
notice how we are still on page number three. 43
43
And so that is a bug that we need to fix. 44
44
Now, can you figure out maybe on your own, 45
45
why does bug is happening? 46
46
So I think that this would be a nice challenge 47
47
for you to pause this video actually 48
48
right now and try to figure out why this bug is happening. 49
49
So hopefully you figured it out. 50
50
And the reason for it is that here in the model, 51
51
when we do the search so here, 52
52
when we load the search results 53
53
of course the state is set to one. 54
54
So the page is set to one here automatically. 55
55
However, as we move to another page 56
56
then this variable here gets updated right. 57
57
But then when we search for something else 58
58
we never reset this page to one right? 59
59
And so that's what we have to do right here 60
60
where we load the search results. 61
61
So after this here, we need to say state.search.page 62
62
and set it back to once. 63
63
And so now whenever we load some new search results 64
64
so basically whenever we do a new search 65
65
then the page will reset to one. 66
66
So let's try that again now. 67
67
So we are again at page three and you already see, 68
68
we have different results. 69
69
And indeed now we are at page number one. 70
70
Okay so that was a small bug that needed to be fixed. 71
71
But now let's go back to the actual topic of this video, 72
72
which is to implement bookmarking. 73
73
So bookmarks are all about data. 74
74
And so we will start by working again in the model 75
75
and we will add a new method here. 76
76
Well actually a new function 77
77
that we export that we will then use from the controller, 78
78
which is simply add a bookmark. 79
79
And so this will receive basically a recipe 80
80
and then it will set that recipe as a bookmark. 81
81
So a recipe and then in our state, 82
82
we already have an array for bookmarks 83
83
or actually we don't, but I think I had it 84
84
in the architecture diagram. 85
85
So anyway, we have an array of bookmarks, 86
86
which we start as an empty array, 87
87
but then basically adding a bookmark 88
88
simply means to push the recipe here into this array. 89
89
Okay so what I just said is this state.bookmarks.push 90
90
and then the recipe object that we just received here. 91
91
So let's add a comment here 92
92
add bookmark because besides this 93
93
we also want to mark the current recipe as being bookmarked. 94
94
So at least if the current recipe is the same recipe 95
95
as this one that we are adding here. 96
96
So mark current recipe as bookmark 97
97
because this will then allow us to actually display 98
98
this current recipe as bookmarked in the recipe view. 99
99
So we can say if recipe.id. 100
100
So the idea of the recipe that we passed in here 101
101
is equal to the ID of the current recipe. 102
102
So the one that is currently loaded in our application 103
103
which is state.recipe.id, while in this case 104
104
we want to say state.recipe.bookmarked should be true. 105
105
So basically setting a new property on this recipe object. 106
106
So for now that is the add bookmark function here. 107
107
And so now let's create a new controller. 108
108
So a controller for adding a new bookmark, 109
109
so control, add bookmark. 110
110
And so here let's not try to add a bookmark 111
111
with the current recipe. 112
112
So model.state.recipe 113
113
and then let's also immediately log that to the console 114
114
so that we can see that it is actually marked as a bookmark. 115
115
And now of course we need a way of calling this 116
116
a controller function. 117
117
So when will that happen? 118
118
Well, it should happen when we click on this button right? 119
119
So this bookmark button 120
120
and right now the icon here is actually wrong. 121
121
So let's start by fixing that here in the recipe view. 122
122
So where is that, 123
123
here. 124
124
So here it should not be fill for now, 125
125
it should simply be the empty icon like this. 126
126
All right. 127
127
Now the name of this button here is button round 128
128
but let's add a another class here. 129
129
So let's say button 130
130
bookmark, and so now we want to listen for clicks 131
131
on this element. 132
132
However, to keep this view simple 133
133
I will not select this element, so at least not directly. 134
134
And instead I will once again, do event delegation. 135
135
So here let's add another function called addHandler 136
136
and hear add bookmark. 137
137
Which has always will receive a handler function 138
138
which in this case is going to be the controller, 139
139
we just created a minute ago. 140
140
So here this.parentelement.event listener click, 141
141
and then, or a function here. 142
142
And so in fact this is really necessary 143
143
because the element that we are trying to select. 144
144
So this button with this class 145
145
of a button bookmark does actually not exist 146
146
by the time the application is loaded, right. 147
147
So basically by the time that the page starts 148
148
this element does not exist. 149
149
And so it's impossible to add an event listener 150
150
to an element that doesn't exist. 151
151
And so that is yet another great use case 152
152
for event delegation. 153
153
So we do exactly what we do here 154
154
which is to simply listen for the event on a parent element 155
155
and then try to figure out if the click actually happened 156
156
on the element that we are looking for. 157
157
And so once again, we will do a button element here 158
158
and then e.target.closest, because one more time 159
159
the user might actually click on the icon element. 160
160
So on the SVG data is in there. 161
161
Okay and if there is a button 162
162
or let's actually say, if there is no button 163
163
then return so the same guard clause as always 164
164
and otherwise call or handler. 165
165
So this was pretty straight forward I believe 166
166
because we have done this many times before. 167
167
Okay and so now 168
168
all we have to do is in the controller module 169
169
to call this method here right. 170
170
So recipe, view.addhandler add bookmark 171
171
and then we pass in control add bookmark. 172
172
And so then when we click the element that we just selected 173
173
then we will add the current recipe as a bookmark 174
174
and prologue also that current recipe to the console 175
175
so that we can see that it was actually marked 176
176
as bookmarked. 177
177
Okay so lets the reload just to make sure 178
178
let's click the button. 179
179
And did anything happen? 180
180
Oh yeah, I think it just 181
181
yeah locked this object here. 182
182
So let's see. 183
183
Ah, and here we have it. 184
184
So bookmarked is now set to true. 185
185
Great. 186
186
So an important piece of the work here is already done 187
187
but now we then want to render here this icon as filled. 188
188
And so let's go back to our view and basically say 189
189
if bookmarked is true, then a render the filled icon. 190
190
And if not, then simply render this one. 191
191
So that should be easy enough. 192
192
So not here in the view, of course 193
193
but in the recipe view where regenerate a markup. 194
194
So yeah, this is the button here, and this is the icon 195
195
that I'm talking about. 196
196
So here, when the recipe is bookmarked 197
197
we want to add like this fill part. 198
198
And so we can simply say this.data 199
199
which is the recipe.bookmarked. 200
200
So if so then here create a fill and otherwise nothing. 201
201
Okay and now finally, to actually make this work 202
202
of course, we will also have to update the entire recipe. 203
203
So recipe view and so this is why we created 204
204
that update method before. 205
205
And so now again, this method is coming in very useful 206
206
because otherwise we would have to render the entire page 207
207
or actually the entire view 208
208
which would make a lot of sense 209
209
because with this we will only update the element 210
210
which has actually changed. 211
211
And so here then again we need to pass in the data 212
212
that we want to update. 213
213
And so that's model.state.recipe once again. 214
214
Okay and so now as we click here 215
215
let's see, and indeed the button was updated. 216
216
Now we get all of these logs here. 217
217
Let's take them out that is in the view. 218
218
So that's this one here. 219
219
Great. 220
220
So here, let's now search for something. 221
221
So let's mark this one here as a bookmark, 222
222
then this one here 223
223
but now as we come back here, let's see what happens. 224
224
And you see that the bookmark is actually gone, 225
225
right? 226
226
So now here you no longer see bookmarked set to true. 227
227
So why is that? 228
228
Well, as we load each new recipe 229
229
it will always be loaded basically from scratch. 230
230
So it will be loaded from the API, right? 231
231
We are not loading this recipe from the bookmarks. 232
232
And actually we won't do that. 233
233
But what we will do is to now use the data that we store 234
234
in the bookmarks array and the state 235
235
to basically Mark any recipe that we load as bookmarked, 236
236
if it is already in the bookmarks array. 237
237
So that probably sounded more complicated 238
238
than it actually is. 239
239
Okay so let's go here back to the model 240
240
and then to our function, which loads the recipe. 241
241
So that is this one. 242
242
So here the as we got all this data 243
243
and store it in the state. 244
244
Then what we can do is to check if there is already a recipe 245
245
with the same ID in the bookmarks state. 246
246
And if it is then we will mark the current recipe 247
247
that we just loaded from the API as bookmarked set to true. 248
248
So let's use 249
249
one of the nice array methods that we learned about, 250
250
which is the sum method. 251
251
And remember that the sum method returns true or false. 252
252
And so that's great for doing an if check like this. 253
253
So here we can check if state.bookmarks.some 254
254
which basically means any, 255
255
so at least that's how I like to think about this method. 256
256
So this method will loop over an array 257
257
and then return true if any of them actually has to 258
258
for the condition that we specify here. 259
259
So if bookmark.id is the same 260
260
as the ID that we just received here 261
261
okay, let's call this here bookmark actually. 262
262
And so basically what this means is that 263
263
if there is any bookmark, which has the bookmark ID 264
264
equal to the ID that we just received 265
265
well, then we want the current recipe 266
266
which is state.recipe to be bookmarked. 267
267
So bookmark equal to true. 268
268
Okay and otherwise we wanted a set to false. 269
269
And so with this, all the recipes that we now load 270
270
we'll always have bookmarked set to either true or false. 271
271
Okay great. 272
272
And so now we actually used this state.bookmarks 273
273
for anything meaningful. 274
274
So up until this point, we had stored the recipe 275
275
in the bookmarks array, but it wasn't really useful. 276
276
So there was really no point up until now, 277
277
but now here use basically use this array 278
278
in order to store all the bookmarks 279
279
so that when we come back to one of them, 280
280
we can then mark the recipe as being bookmarked. 281
281
So let's try this now again. 282
282
So bookmarking this, then I come to this 283
283
and yeah so that worked and you see that it is bookmarked 284
284
set to true and the previous one. 285
285
So the double crust stuffed pizza 286
286
is of course bookmarked set to false. 287
287
And so when we click that here, 288
288
it doesn't have the bookmark. 289
289
Now we bookmarked it. 290
290
And when we come back to it, then there it is. 291
291
Okay and now just as the final piece here, 292
292
when we click on this button again 293
293
we then want to unbookmark basically this recipe. 294
294
So we want to remove it from the bookmarks 295
295
but right now, of course, that doesn't happen. 296
296
And so what we need now is basically yet another method 297
297
or function here in our model, 298
298
which will simply remove a bookmark. 299
299
So doing the opposite of add bookmark. 300
300
So const delete bookmark 301
301
and this one will simply receive an ID 302
302
because that is actually simpler. 303
303
And this is actually a common pattern 304
304
that you will see in programming when we add something 305
305
we get the entire data. 306
306
And when we want to delete something, we only get to the ID. 307
307
So this is a pretty common pattern again. 308
308
So what we want to do here is to basically delete the recipe 309
309
which has this ID from the bookmarks array right? 310
310
So state.bookmarks and then to delete something, 311
311
we use the splice method. 312
312
Remember, and then here we need the index 313
313
where the element is actually located 314
314
that we want to delete. 315
315
So we will calculate the index in a second. 316
316
And then how many items we want to delete 317
317
which has only one. 318
318
And so this index here, we can calculate it by using 319
319
our old friend defined index method. 320
320
So state.bookmarks. 321
321
And I think we already did something very similar to this 322
322
in the Bankist application. 323
323
So here we are looking for the element 324
324
which has the ID equal to the ID that was passed in. 325
325
So there's going to be one bookmark 326
326
for which this condition here is true. 327
327
So word current bookmark.id is equal to this ID. 328
328
And so for this element where this condition is true 329
329
the index will be returned. 330
330
And then we can take that index and deleted from the array. 331
331
And then finally, let's also mark the current recipe 332
332
as not a bookmark anymore. 333
333
So as not bookmarked and here as well, 334
334
and here let's say delete bookmark, okay. 335
335
And now we need to of course use this function somewhere. 336
336
And that's always, that can only be in the controller. 337
337
Okay, so this control add bookmark function will be executed 338
338
whenever we click on that bookmark button. 339
339
And so here we now need to control 340
340
what exactly should happen in that case. 341
341
So when do we actually want to add a bookmark? 342
342
Well, actually only when the recipe is not yet bookmarked. 343
343
So let's write that. 344
344
So if model.state.recipe.bookmarked 345
345
so if that's false, 346
346
then do this. 347
347
So add to bookmark then but if not, 348
348
and so let's now do this instead of an else 349
349
because this is more readable 350
350
then we want to delete bookmark. 351
351
And again, here we pass in actually the ID like this 352
352
and that's actually it, and this is possible. 353
353
Remember so it's possible that we read the bookmark property 354
354
right at the beginning 355
355
because we add that to all the recipes 356
356
that are ever loaded right at the beginning right here. 357
357
Okay and so now this should not work. 358
358
Let's try avocado now for a change. 359
359
So some sushi here that looks delicious 360
360
and we get ourselves a bug. 361
361
So let's go to line number eight, 98 actually. 362
362
So 98. 363
363
Oh and here we are using recipe.id 364
364
because we simply copied it from here. 365
365
So you see that simply copying some code many times can 366
366
make us run into bugs. 367
367
So here, of course we are already receiving the ID. 368
368
So that's only ID let's go back 369
369
and let's search for avocado again. 370
370
So here we have that let's bookmark it. 371
371
Well, that didn't work. 372
372
Let's see why, so probably something wrong 373
373
in our controller. 374
374
So let's lock this year to the console, 375
375
just to see if this is having any effect 376
376
let's clear this here, and it is false. 377
377
And so, 378
378
therefore this should have worked 379
379
but somehow nothing worked. 380
380
So this code here did not get executed for some reason. 381
381
Oh and actually I see what is happening. 382
382
So this code actually did get executed. 383
383
So this code here, will mark the recipe as bookmarked, 384
384
but then in the next line of code right here, 385
385
then the recipe is already bookmarked. 386
386
And so then it will delete that bookmark. 387
387
And so here, actually we need an else. 388
388
Okay so that's the kind of sometimes difficult 389
389
bugs to find, but I'm sure that with time, 390
390
you will also be able to find all of these bug. 391
391
So let's click on some recipe here, mark it as a bookmark. 392
392
Then we go here to some other one mark that. 393
393
Then here, that is still working and now let's click 394
394
and see if it disappears. 395
395
And yes, it does. 396
396
Now do the same here, come back. 397
397
And it is still unbookmarked. 398
398
Well, all right. 399
399
So with this, we have two core functionality 400
400
of bookmarking actually already implemented. 401
401
So great job once again. 402
402
And now all that is missing 403
403
is that we display all our bookmarks up here 404
404
in this bookmarks panel. 405
405
And that is a little bit more work than it might sound. 406
406
And so that's leave that for our next video.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.