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
Okay, so let's now implement 2
2
the feature of updating recipe servings. 3
3
And this time, we're actually starting in the controller, 4
4
just so we can outline what we want to happen. 5
5
So let's come down here and add yet another controller. 6
6
So control servings, let's say. 7
7
And I keep calling these functions here, controllers, 8
8
but that's just because we're using 9
9
the model view controller pattern. 10
10
So they could also be called handlers, because in the end, 11
11
that's what they are, they are simply event handlers, 12
12
that will run whenever some event happens. 13
13
Now, in this case, this controller here 14
14
will eventually be executed when the user clicks 15
15
on one of these buttons here. 16
16
So either to decrease, or to increase the servings. 17
17
And so that will then increase or decrease this number here, 18
18
and also adjust all of these ingredients, right? 19
19
So this controller is actually going to be very simple. 20
20
All we have to do here is to update the recipe servings, 21
21
so in the state. 22
22
So basically updating the underlying data. 23
23
And then all we have to do is to update the view as well. 24
24
So actually updating the recipe view, 25
25
because that is of course, the view that will be impacted 26
26
by controlling the servings, right? 27
27
So in this case, we will actually have no, 28
28
like servings view, because these buttons, 29
29
and everything that happens when we click on them 30
30
is already in the recipe view, all right? 31
31
So here, updating the servings in the state 32
32
has of course to do with the model. 33
33
And so in the model, we would like to have 34
34
some method which does that for us. 35
35
So as always, we will not want to manipulate data 36
36
directly here in a controller, 37
37
instead we delegate that task to the model, 38
38
which is all about the data. 39
39
So again, in the model, we will like to have 40
40
a method called update servings, 41
41
and then we can pass in the new servings. 42
42
So let's just say six here, for experimenting. 43
43
And so let's, now go to the model 44
44
and actually implement this. 45
45
So load recipe, then results, 46
46
then here, we will have the update servings function. 47
47
And so this will then take in the number of servings, 48
48
let's call it new servings, actually. 49
49
Now what this function will do is to reach into the state, 50
50
and in particular into the recipe ingredients, 51
51
and then change the quantity in each ingredient. 52
52
So we have state.recipe, 53
53
and then we have that ingredients array, ingredients. 54
54
And so again, in each ingredient, 55
55
we now want to change the quantity property. 56
56
So just to remember, again, our data, because I know 57
57
this can be quite confusing, let's do a search here, 58
58
because that will then change us, 59
59
or actually it will show us here some real data. 60
60
So here is a recipe. 61
61
Ah, this is actually only the search data. 62
62
But this is the actual data here, so for the entire recipe. 63
63
And so remember that we have two ingredients in there 64
64
and each ingredient is an object, 65
65
which contains the quantity. 66
66
And so this is the quantity we want to change. 67
67
For example, here this quantity two is four four servings, 68
68
but if we had eight servings, 69
69
then the quantity should become eight, right? 70
70
So the servings doubled, 71
71
and so the quantity needs to double as well. 72
72
And so that's the kind of logic that we will write now. 73
73
And so, yeah, this was just to show you 74
74
that it is the quantity property 75
75
inside of the ingredient that we will want to mutate. 76
76
So we want to do something for each of these ingredients. 77
77
So we don't want a new array, and we could do that also. 78
78
So we could create a new array, 79
79
and then override state.recipe. 80
80
But let's just do it like this. 81
81
So basically with side effects. 82
82
So in each iteration of the loop, 83
83
we have the current ingredient. 84
84
And then here, we want to do something with it. 85
85
So basically, we want to change it. 86
86
So ingredients.quantity, should become something new. 87
87
And now how do we calculate this new quantity? 88
88
Well, we will basically use this formula. 89
89
So let me write that here. 90
90
So new quantity equals the old quantity 91
91
times the new servings divided by the old servings. 92
92
And let's use the example that I mentioned earlier. 93
93
So changing from four servings to eight servings. 94
94
And I think we had the quantity of two. 95
95
So two times, and then the new servings again, 96
96
were eight divided by four. 97
97
And so this would then be eight divided by four is two, 98
98
times two is four. 99
99
So again, if we double the servings like this, 100
100
then we also need to double the quantity. 101
101
So we then multiply the original quantity 102
102
by this ratio here, basically. 103
103
Now okay, so just basic mathematics here. 104
104
And so let's not put this formula here. 105
105
So the old quantity is in this case, 106
106
also ingredients.quantity, so the original one, 107
107
and then times the new servings. 108
108
So the one we are getting here, 109
109
divided by state.recipe.servings, now, okay. 110
110
So with this, we are changing all the ingredients. 111
111
In order to finish, of course, 112
112
we also need to update the servings in the state. 113
113
Because otherwise, if we tried to update the servings twice, 114
114
then by the second time, we would still be using 115
115
the old value of two servings. 116
116
And so of course, we need to update this value. 117
117
So state.recipe.servings, needs to be the new servings. 118
118
And we're doing that here at the end of the function, 119
119
because otherwise, we could not preserve this old. 120
120
So this original value here, okay? 121
121
So this, we update the servings of the current recipe. 122
122
And again, that works because we already have 123
123
the recipe in the state. 124
124
Okay, and so then we need to simply update the recipe view. 125
125
And by now what we will do is to actually simply overwrite 126
126
the complete recipe. 127
127
So basically, we will simply render it again. 128
128
So exactly what we had here actually, in control recipes. 129
129
So taking the recipe out of the state, 130
130
and then simply rendering it. 131
131
So let's copy this down here. 132
132
So we do that, because we don't want to 133
133
like manually go ahead and 134
134
change all these values here one by one. 135
135
So we would have to select this element and this element, 136
136
and this one, and then manually change all of that. 137
137
And the same here for this value, right? 138
138
And so we don't want to have all of that work. 139
139
And so for now, we will simply, 140
140
well update this entire element here again, 141
141
so this entire view, okay? 142
142
And now let's actually call this controller here, 143
143
without having to create the event listener just yet. 144
144
So just to test if everything is working. 145
145
And so let's do that, after all of this. 146
146
So here in the init function at the end, 147
147
we call control servings. 148
148
And so with this, we can guarantee 149
149
that there is already a recipe loaded. 150
150
So let's actually use the example of eight here 151
151
so that we double the values. 152
152
Not well, that's not really working. 153
153
There seems to be some kind of bug here. 154
154
Oh, and for each is of course, wrong here. 155
155
But we also have some other problem here apparently, 156
156
which is that we are trying to read for each on undefined. 157
157
So let's first fix that small error. 158
158
So it's called for each. 159
159
And then that other problem actually comes from the fact 160
160
that we are doing it wrong. 161
161
So we are not taking into account the asynchronous nature 162
162
of our application here. 163
163
So, basically, here, we are trying to control the servings 164
164
simply after registering these handler functions here. 165
165
But by that time, no recipe has yet arrived from the API. 166
166
And so therefore, state.recipe is not yet defined. 167
167
And so here we are then trying to read ingredients 168
168
from the recipe that doesn't exist, okay? 169
169
Does that make sense? 170
170
And this is actually a great demonstration of the pitfalls 171
171
of working with Asynchronous JavaScript. 172
172
So if we really wanted to test this here right now, 173
173
we could probably do that right here, 174
174
after we control the recipes. 175
175
So basically, after the recipe is loaded. 176
176
So let's just temporarily put this here, 177
177
or probably even better, right here. 178
178
Let's just mark this very clearly as a test, all right? 179
179
And let's see what happens now. 180
180
Oh, and now we have the eight servings that we want. 181
181
And here, these values, they should have changed. 182
182
Well, I'm not sure what they looked like before. 183
183
But we can reach here now, 184
184
but here we also already have the eight servings. 185
185
So this is not a good comparison. 186
186
But let's try it here with four. 187
187
And so we have four. 188
188
And yeah, these values are actually half 189
189
of what they were before. 190
190
And so that means that our update servings function 191
191
is already doing its job, so that's great. 192
192
So we can remove that from here 193
193
because now we will actually want the controller to run 194
194
whenever we click one of the buttons in the recipe view. 195
195
And so what we will do now is to create 196
196
a new event listener in the recipe. 197
197
So here in this recipe view. 198
198
And again, that's because that's 199
199
where these buttons already are. 200
200
And so there is no need to create a new, like servings view. 201
201
So here, I will simply create a new method. 202
202
And as always, it's called add handler and then something. 203
203
So here, let's call it update servings, 204
204
to make its purpose really clear 205
205
and then as always the handler function. 206
206
And again, that handler function will of course, 207
207
then be debt controller that we just wrote here, okay? 208
208
Now, how will we actually do this? 209
209
So the parent element here is this whole recipe, 210
210
but the elements that we are interested in, 211
211
are these two buttons. 212
212
So these buttons increase servings, 213
213
end button decrease servings. 214
214
And the class that they have both in common, 215
215
is this button tiny, right 216
216
Now, each of these buttons also 217
217
has some elements inside of it. 218
218
And so yeah, the best way of doing this 219
219
is actually once again, doing event delegation. 220
220
So we already have the parent element. 221
221
And so we can listen for events on that one. 222
222
And then check if the click target was one of those buttons. 223
223
And so this is actually going to be very similar 224
224
to what we did in the last video 225
225
with the pagination buttons. 226
226
So add event listener, click. 227
227
And then here again, we want to actually select 228
228
that button element that was clicked or not. 229
229
So here we then use again, event.target, 230
230
which is the clicked element. 231
231
And then once again, we use the closest method, 232
232
which is, I think I've said it before, an amazing method, 233
233
which is really, really useful for event delegation. 234
234
And so again, we are looking for 235
235
elements with the button tiny class. 236
236
So button tiny and that is important because 237
237
the user might click, actually on this. 238
238
So on this SVG element instead of the button element itself, 239
239
and so then that will basically look 240
240
for the closest button tiny, right? 241
241
But of course, if we're clicking outside 242
242
of any of these buttons, then this closest 243
243
will not return any element, it will return null. 244
244
And so we need to check for that, just like before. 245
245
So if null button, then return. 246
246
But otherwise, let's simply for now login to the console. 247
247
And so now we need to connect this here with a controller. 248
248
And so let's do that. 249
249
So that's, and let's actually do this here. 250
250
So keep it close to the other recipe view. 251
251
So recipe view.add handler update servings, 252
252
which will then receive control servings, 253
253
so that it can execute our controller function. 254
254
And so if we now put some value here, let's say eight, 255
255
then that should actually already update the servings 256
256
and re render the recipe view. 257
257
So let's see. 258
258
Let's take a look here at this value and these values here. 259
259
Oh, and nothing happened because of course, we didn't call. 260
260
So here, we didn't call control recipes yet, right? 261
261
So we didn't call the handler function. 262
262
But let's actually do that, now, right. 263
263
And you see that the number here change to eight. 264
264
And here all the values changed as well. 265
265
So that's great means again, 266
266
that our update servings function is doing its job. 267
267
And the same can be set for control servings. 268
268
Now, we can also see that 269
269
the correct button here was selected. 270
270
Now it's actually not showing it anymore, here. 271
271
But that's probably because the DOM was re rendered here. 272
272
And so this new button is not exactly 273
273
this button that we have here. 274
274
But that doesn't really matter 275
275
because all I wanted was to check 276
276
if the selection was correct here, and it was. 277
277
So let's try that again now with the increase button, 278
278
and watch again what happens with ingredients, okay? 279
279
And so here, we got the button increased servings. 280
280
Now okay, so we're almost done here. 281
281
Now, all we want to do is, of course, 282
282
to decrease the value when we click here, 283
283
and increase the value when we click the plus button. 284
284
And so we don't want to always set the value to eight, 285
285
but instead, do that dynamically. 286
286
And there are multiple ways in which we can do that. 287
287
So let's think about this a little bit. 288
288
So we could do it right in the controller 289
289
because right here, we already know 290
290
what the current number of servings is. 291
291
And so then here, we could simply take that, 292
292
and decrease or increase that value by one. 293
293
And so that would then yield the effect that we want. 294
294
However, I would like to keep this controller here 295
295
as flexible and as robust as possible. 296
296
And so I don't want this controller 297
297
to be the one responsible for telling, 298
298
which should be the next serving. 299
299
So the next number of servings. 300
300
So that should come from the view, 301
301
and not from the controller, because it is in the view 302
302
where the user is actually updating the servings. 303
303
And so in order to keep this controller 304
304
as flexible as possible, we can simply pass in, 305
305
basically the new servings, 306
306
and then pass that new servings into update servings. 307
307
Okay, so new servings here. 308
308
And then use that here as well. 309
309
And so now we will determine this new servings in the view, 310
310
and pass that value down into this controller, all right? 311
311
But now here in this function, 312
312
how will we determine the new servings? 313
313
Well, once again, here we will need to connect 314
314
the user interface with decode. 315
315
And as always, for that we use the special data properties. 316
316
So let's come to our button or both our buttons 317
317
and then add a new property here. 318
318
And so then we can read the value from that property 319
319
in the Add event listener function. 320
320
So let's say data, update, to. 321
321
And then here the value should be the current servings, 322
322
and plus one, right, because this is the button 323
323
to increase the servings, 324
324
while actually both are called increase, 325
325
but this one has a minus sign. 326
326
So this icon here is called icon minus. 327
327
So that means that we are decreasing the value. 328
328
But anyway, what we want here 329
329
is basically the current servings minus one, right? 330
330
And then in the other button, 331
331
we want the same, but plus one. 332
332
So as I said, in the beginning, 333
333
this is pretty similar to the pagination buttons, 334
334
until let's actually change the increase 335
335
that we have in both to update. 336
336
Okay, and let's then actually use this class 337
337
to select the buttons. 338
338
Because button tiny is a class 339
339
that is actually more about styling, 340
340
and this button update servings 341
341
is more about the functionality, so let's use that one here. 342
342
And so now we can read, now, of course, that value. 343
343
So const update, two equals the button.data set.update to. 344
344
Alright, so here updates two as well. 345
345
And it has this camel case here, 346
346
because when there is a dash in the property name, 347
347
then that will be converted to camelcase notation like this. 348
348
And here, we can actually use destructuring, 349
349
so that makes the code even cleaner. 350
350
Then we can pass that value here to update to, 351
351
and that's it, right? 352
352
Now, here, we just need to convert that to a number, 353
353
but besides that, we should be good to go. 354
354
So it should be working now. 355
355
So instead of changing to the hard coded value of eight 356
356
we had before, let's see what happens now. 357
357
Now we get undefined servings. 358
358
So let's try to understand what's happening. 359
359
But at least the button here was correct. 360
360
So the value used to be four, 361
361
and so the plus button that we clicked 362
362
had the data update to, set to five. 363
363
Okay, so here, let's simply check the value of update to, 364
364
maybe we did something wrong in getting that value. 365
365
Yeah, it looks like there is undefined. 366
366
So let's go back and check what's going on here. 367
367
But it looks correct. 368
368
So update to is not spelled wrong, am I right? 369
369
Update to, man, so, 370
370
well, let's try to get rid of destructuring, 371
371
but that shouldn't be the cause, update to, 372
372
Oh, and actually, that should be the cause 373
373
because of this conversion that we have here. 374
374
So I was trying to convert plus a button data set, 375
375
and then trying to get update to from there. 376
376
So I'm sure that now it will work, but let's see. 377
377
And yes, it does, so now we get the number there. 378
378
So beautiful, and you see the values changing down there. 379
379
And everything works correctly. 380
380
Now there's just this flickering of the image here. 381
381
But we will take care of that in the next lecture. 382
382
For now let's experiment 383
383
and see what happens here at a certain point. 384
384
So here we reach zero servings, 385
385
and then we go even further down. 386
386
And so this of course doesn't make any sense. 387
387
And so we need to add a check here. 388
388
So basically, we only want to call the handler, 389
389
if the number we will update to is greater than zero. 390
390
So we don't want to update to zero or anything below. 391
391
And so then in that case, we simply don't call the handler. 392
392
Okay, now here, let's put it back to the structuring 393
393
like we had it before. 394
394
So I really prefer that. 395
395
And then I will simply do the conversion from the string. 396
396
So right now this is a string. 397
397
So I will simply convert that here, and also here. 398
398
I can also get rid of this console.log here 399
399
to make the function a bit cleaner, and so let's see again. 400
400
So it keeps working here. 401
401
But then as we reach one, it doesn't go any further down. 402
402
Okay, so beautiful, that works. 403
403
But we're still using this kind of hack of updating 404
404
the entire view here at once. 405
405
So remember, here in the controller, 406
406
in order to basically update the recipe view, 407
407
we are simply rendering it all over again. 408
408
And so that takes some time, 409
409
especially noticeable here in the image. 410
410
So you see, I think it's basically trying to download 411
411
the image again, and so that means, of course, trouble. 412
412
And so in the next lecture, 413
413
we will develop a simple algorithm, 414
414
which will basically only update the DOM in places 415
415
where we actually want to update the markup. 416
416
So only, for example, this number here, and these numbers, 417
417
and leaving everything else the same, 418
418
so without re rendering everything, 419
419
and that will be a lot of fun. 420
420
And so let's go do that next.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.