WEBVTT

1
00:00:01.390 --> 00:00:03.390
<v Jonah>So, as I just said,</v>

2
00:00:03.390 --> 00:00:07.670
let's now start with the feature of uploading a new recipe

3
00:00:07.670 --> 00:00:11.870
and start with the ability of opening the model window,

4
00:00:11.870 --> 00:00:15.173
which contains the form to add the new recipe.

5
00:00:16.690 --> 00:00:21.040
So in the demo version, this is what it looks like.

6
00:00:21.040 --> 00:00:23.150
So here we click add recipe,

7
00:00:23.150 --> 00:00:26.160
and then it opens up this form like this,

8
00:00:26.160 --> 00:00:27.980
and then when we click this button,

9
00:00:27.980 --> 00:00:30.170
or click outside of the form,

10
00:00:30.170 --> 00:00:32.743
then that window will again close.

11
00:00:34.160 --> 00:00:36.709
Alright, so let's do that,

12
00:00:36.709 --> 00:00:39.913
and let's create a new bookmark's view.

13
00:00:42.290 --> 00:00:45.220
And actually not a bookmark's view,

14
00:00:45.220 --> 00:00:47.427
but a addRecipeView.js

15
00:00:52.550 --> 00:00:55.510
And now let's go to one of these views,

16
00:00:55.510 --> 00:00:57.233
and copy the code from there.

17
00:01:00.360 --> 00:01:03.533
Because this code is always very similar,

18
00:01:05.420 --> 00:01:08.520
so let's delete this one here,

19
00:01:08.520 --> 00:01:10.733
let's empty out this method.

20
00:01:13.903 --> 00:01:17.270
And then here, let's call it AddRecipeView.

21
00:01:22.220 --> 00:01:26.080
Now this view here is actually gonna be quite different

22
00:01:26.080 --> 00:01:29.126
from the other views because we already have

23
00:01:29.126 --> 00:01:31.963
actually the view in the HTML.

24
00:01:33.530 --> 00:01:36.280
So if we come here to our HTML code,

25
00:01:36.280 --> 00:01:39.609
then you see that the form that we want to display

26
00:01:39.609 --> 00:01:44.609
is actually already here in the code, all right?

27
00:01:45.000 --> 00:01:48.270
So, here we have this element for the overlay

28
00:01:48.270 --> 00:01:50.411
and this element for the window

29
00:01:50.411 --> 00:01:53.540
and they both have the hidden class.

30
00:01:53.540 --> 00:01:56.170
And so showing the window and the overlay

31
00:01:56.170 --> 00:01:59.380
is gonna be as simple as removing this hidden class

32
00:01:59.380 --> 00:02:01.093
from both these elements.

33
00:02:02.140 --> 00:02:04.680
Now, the main element that we are actually

34
00:02:04.680 --> 00:02:08.500
really interested in is this upload element.

35
00:02:08.500 --> 00:02:11.200
And so let's actually make this upload element,

36
00:02:11.200 --> 00:02:14.563
the parent element of the AddRecipeView.

37
00:02:16.330 --> 00:02:19.520
So upload here, but then we will also have

38
00:02:19.520 --> 00:02:23.470
to select some other elements.

39
00:02:23.470 --> 00:02:26.260
So for example, the window and the overlay,

40
00:02:26.260 --> 00:02:28.310
so to start at least.

41
00:02:28.310 --> 00:02:33.257
So the window element is going to be document.querySelector

42
00:02:35.100 --> 00:02:36.950
and then let's see what we have here.

43
00:02:38.040 --> 00:02:40.343
Here we can close all of these for now.

44
00:02:41.400 --> 00:02:44.160
So that's add recipe window.

45
00:02:44.160 --> 00:02:47.193
And then the overlay has simply the overlay class.

46
00:02:50.570 --> 00:02:55.570
And so here, overlay and here as well.

47
00:02:57.090 --> 00:03:01.787
And here we are missing the dot on both selectors.

48
00:03:01.787 --> 00:03:04.530
And now we also need to select a button

49
00:03:04.530 --> 00:03:06.840
that will be clicked to open the window

50
00:03:06.840 --> 00:03:10.493
and also the button to close the window.

51
00:03:11.510 --> 00:03:15.353
So that button is somewhere here in the top navigation bar.

52
00:03:16.940 --> 00:03:21.940
So this is for the bookmarks and here it is.

53
00:03:23.810 --> 00:03:27.083
So this is the button for adding the recipe as you see.

54
00:03:28.500 --> 00:03:30.590
So let's call that the btnOpen

55
00:03:37.179 --> 00:03:40.014
and then also the button to close the form.

56
00:03:40.014 --> 00:03:43.295
And so that's back here somewhere in the window.

57
00:03:43.295 --> 00:03:45.462
So that's btn-close-model.

58
00:03:48.987 --> 00:03:50.237
Okay, and here.

59
00:03:55.594 --> 00:03:59.523
Okay and so now, let's listen for the events,

60
00:03:59.523 --> 00:04:03.856
so of clicking the open button and the close button.

61
00:04:04.970 --> 00:04:08.500
Okay, and as always, we will do that in a method called

62
00:04:08.500 --> 00:04:11.280
addHandler and then something,

63
00:04:11.280 --> 00:04:13.043
just to make it more consistent.

64
00:04:13.920 --> 00:04:18.713
So addHandlerShowWindow, let's say,

65
00:04:21.270 --> 00:04:23.913
and so here we will want to select the button.

66
00:04:25.240 --> 00:04:30.240
So btnOpen.addEventListener of a click.

67
00:04:33.380 --> 00:04:36.883
And so when that happens, what do we want to do?

68
00:04:37.870 --> 00:04:41.560
Well, we want to take the overlay into window

69
00:04:41.560 --> 00:04:44.470
and remove the hidden class.

70
00:04:44.470 --> 00:04:49.470
So that's this.overlay.classList.rem.

71
00:04:55.750 --> 00:04:59.960
Now, instead of remove, we can actually also use toggle.

72
00:04:59.960 --> 00:05:04.010
So remember that toggle will add to class if it's not there

73
00:05:04.010 --> 00:05:06.680
and it will remove the class when it is already there.

74
00:05:06.680 --> 00:05:09.174
And so this will make it a lot easier

75
00:05:09.174 --> 00:05:11.663
to then reuse this class.

76
00:05:12.880 --> 00:05:16.623
So the overlay and also the window.

77
00:05:18.950 --> 00:05:22.090
Okay, now, when do we actually want

78
00:05:22.090 --> 00:05:24.283
this function here to be called?

79
00:05:26.010 --> 00:05:30.540
Well, we want this to be called as soon as the page loads.

80
00:05:30.540 --> 00:05:32.600
Now, in this case, this has nothing to do

81
00:05:32.600 --> 00:05:36.080
with any controller because there is nothing special

82
00:05:36.080 --> 00:05:40.620
happening here that the controller needs to tell us, right?

83
00:05:40.620 --> 00:05:44.020
So when this click happens on the button open,

84
00:05:44.020 --> 00:05:47.885
all that will happen is really for the window to show.

85
00:05:47.885 --> 00:05:50.600
So the controller, it doesn't need to interfere

86
00:05:50.600 --> 00:05:54.010
in any of this and so therefore we can simply run

87
00:05:54.010 --> 00:05:58.123
this function here as soon as this object is created.

88
00:05:59.980 --> 00:06:01.820
And so what I'm gonna do is

89
00:06:01.820 --> 00:06:04.263
to this time add a constructor method,

90
00:06:07.100 --> 00:06:09.220
then since this is a child class,

91
00:06:09.220 --> 00:06:12.133
we need to start by calling super.

92
00:06:13.230 --> 00:06:16.450
And so only after that, we can use the this keywords.

93
00:06:16.450 --> 00:06:18.750
And then let's say, this.addHandlerShowWindow.

94
00:06:22.446 --> 00:06:25.780
And so this one here is now only gonna be

95
00:06:25.780 --> 00:06:28.240
used inside of this class.

96
00:06:28.240 --> 00:06:33.240
And so let's add an underscore to mark it as protected.

97
00:06:34.340 --> 00:06:37.790
And so again, in order to show this window,

98
00:06:37.790 --> 00:06:42.110
the controller does not interfere at all, all right?

99
00:06:42.110 --> 00:06:44.805
Now what we will have to do in the controller still

100
00:06:44.805 --> 00:06:48.360
is to import this object here

101
00:06:48.360 --> 00:06:52.430
because otherwise, our main script sort of controller

102
00:06:52.430 --> 00:06:54.490
will never execute this file.

103
00:06:54.490 --> 00:06:58.000
And so then this object here will never be created.

104
00:06:58.000 --> 00:07:01.593
And so the event listener here will never be added.

105
00:07:02.550 --> 00:07:05.060
And so we need to, again, import this

106
00:07:05.060 --> 00:07:07.010
so that the code that is in the module

107
00:07:07.010 --> 00:07:08.563
is actually being run.

108
00:07:11.620 --> 00:07:16.620
So here let's call that the AddRecipeView.

109
00:07:21.360 --> 00:07:23.830
And now let's check out our code

110
00:07:23.830 --> 00:07:25.893
just to make sure we reload it.

111
00:07:27.230 --> 00:07:30.653
And we got a class list of undefined.

112
00:07:31.760 --> 00:07:34.690
So some small bug here, and again,

113
00:07:34.690 --> 00:07:36.643
you see how common that is.

114
00:07:38.130 --> 00:07:41.350
So let's again, see which line that actually was.

115
00:07:41.350 --> 00:07:42.653
So line 19.

116
00:07:43.660 --> 00:07:45.633
So with the overlay.

117
00:07:46.890 --> 00:07:48.943
So let's see if the class is correct.

118
00:07:51.320 --> 00:07:52.663
Well, it looks so.

119
00:07:56.010 --> 00:07:58.730
No, but I can see the error now.

120
00:07:58.730 --> 00:08:00.860
So here we are using the this keyword

121
00:08:00.860 --> 00:08:03.390
inside of a handler, right?

122
00:08:03.390 --> 00:08:05.840
But you already know that the this keyword

123
00:08:05.840 --> 00:08:08.717
inside of a handler function points to the element

124
00:08:08.717 --> 00:08:12.320
on which that listener is attached to.

125
00:08:12.320 --> 00:08:15.023
So in this case, that is this button here.

126
00:08:15.900 --> 00:08:19.490
And so let's actually export this entire function

127
00:08:19.490 --> 00:08:22.283
into another method and then call that method

128
00:08:22.283 --> 00:08:25.963
with the correct this keyword bound to it.

129
00:08:28.000 --> 00:08:31.937
So here is what I mean, toggleWindow, let's say,

130
00:08:36.770 --> 00:08:38.810
will do this and then here,

131
00:08:38.810 --> 00:08:43.597
we want to call this.toggleWindow.

132
00:08:44.610 --> 00:08:48.980
And now here we can use our bind method as always,

133
00:08:48.980 --> 00:08:51.930
and then bind the correct this keyword.

134
00:08:51.930 --> 00:08:54.075
So we have done this many times before,

135
00:08:54.075 --> 00:08:57.230
so basically manually setting the this keyword

136
00:08:57.230 --> 00:08:59.770
inside of this function here,

137
00:08:59.770 --> 00:09:03.232
now to the this keyword that we actually want it to be.

138
00:09:03.232 --> 00:09:06.210
And so right here, this of course,

139
00:09:06.210 --> 00:09:08.660
points to the current object

140
00:09:08.660 --> 00:09:11.630
because otherwise, again, the this keywords

141
00:09:11.630 --> 00:09:15.810
inside of this function would be the button

142
00:09:15.810 --> 00:09:17.973
on which the event listener is attached to.

143
00:09:19.050 --> 00:09:22.803
And so with this, it should now work and yeah,

144
00:09:23.740 --> 00:09:25.373
there is our form.

145
00:09:26.470 --> 00:09:29.140
And now, all we have to do is to close that form

146
00:09:29.140 --> 00:09:32.453
when we click this button or click outside here.

147
00:09:36.600 --> 00:09:37.900
So addHandlerHeightWindow.

148
00:09:44.540 --> 00:09:48.160
And so that's actually very similar to this one,

149
00:09:48.160 --> 00:09:50.653
that's just duplicated actually.

150
00:09:53.400 --> 00:09:58.400
So btnClose and then the same also on the overlay.

151
00:10:00.900 --> 00:10:02.750
And so that's why this toggle here

152
00:10:02.750 --> 00:10:06.050
is now very useful because here at this point,

153
00:10:06.050 --> 00:10:08.259
when we want to hide the window,

154
00:10:08.259 --> 00:10:11.040
then the hidden class is no longer there,

155
00:10:11.040 --> 00:10:13.823
but it will then automatically add it back on.

156
00:10:16.040 --> 00:10:18.837
Now, and before we actually try it,

157
00:10:18.837 --> 00:10:23.003
we first of course, need to call this method here as well.

158
00:10:28.500 --> 00:10:31.303
Okay, and it's gone.

159
00:10:32.670 --> 00:10:35.800
Great, so that works.

160
00:10:35.800 --> 00:10:40.390
And so next up, let's take care of handling this button here

161
00:10:40.390 --> 00:10:42.020
and for now what we want to do

162
00:10:42.020 --> 00:10:45.330
when we click this button is to get all the data here

163
00:10:45.330 --> 00:10:46.653
out of this form.

164
00:10:47.510 --> 00:10:49.610
And you see that I already have like,

165
00:10:49.610 --> 00:10:51.570
pre-filled this data here.

166
00:10:51.570 --> 00:10:56.090
And so that comes from the HTML here

167
00:10:56.090 --> 00:10:58.927
because the value is basically already set.

168
00:10:58.927 --> 00:11:02.780
But then of course, by the end, we will remove this.

169
00:11:02.780 --> 00:11:05.163
So this is just for development purposes.

170
00:11:07.550 --> 00:11:11.680
But anyway, let's now create another method here,

171
00:11:11.680 --> 00:11:16.620
which is going to handle the click on that button.

172
00:11:16.620 --> 00:11:19.053
So basically the form submission.

173
00:11:23.440 --> 00:11:25.290
So addHandlerUpload.

174
00:11:28.990 --> 00:11:32.970
And so here we will now actually listen for an event

175
00:11:32.970 --> 00:11:35.240
right on the parent element.

176
00:11:35.240 --> 00:11:37.423
So that is the upload form itself.

177
00:11:38.790 --> 00:11:42.865
So parentElement.addEventListener

178
00:11:42.865 --> 00:11:47.547
for submit and then inner function as always,

179
00:11:49.350 --> 00:11:52.640
the first thing is to prevent default.

180
00:11:52.640 --> 00:11:57.640
So here we need access to the event, prevent default.

181
00:11:59.140 --> 00:12:03.653
And now how do we get access to all of these values?

182
00:12:04.550 --> 00:12:07.010
Well, we could go ahead and select

183
00:12:07.010 --> 00:12:09.337
all of these form elements one by one,

184
00:12:09.337 --> 00:12:13.750
and then read the value property of all of them.

185
00:12:13.750 --> 00:12:17.000
However, there is actually an easier way

186
00:12:17.000 --> 00:12:20.173
because we can use something called form data.

187
00:12:22.450 --> 00:12:25.720
So that's a pretty modern browser API

188
00:12:25.720 --> 00:12:27.763
that we can now make use of.

189
00:12:29.300 --> 00:12:31.260
So let's say data equals

190
00:12:31.260 --> 00:12:34.970
and then we can create a new form data

191
00:12:35.870 --> 00:12:38.370
and into the form data constructor,

192
00:12:38.370 --> 00:12:41.960
we have to pass in an element that is a form.

193
00:12:41.960 --> 00:12:46.960
And so that form in this case is the this keyword, right?

194
00:12:47.130 --> 00:12:50.190
Because we are inside of a handler function.

195
00:12:50.190 --> 00:12:52.463
And so this points to this.parentElement,

196
00:12:53.550 --> 00:12:56.770
which is of course the upload form.

197
00:12:56.770 --> 00:13:00.230
Now this here will then return a weird object

198
00:13:00.230 --> 00:13:02.160
that we cannot really use,

199
00:13:02.160 --> 00:13:04.980
but we can actually spread that object

200
00:13:04.980 --> 00:13:09.670
into an array, like this, all right?

201
00:13:09.670 --> 00:13:13.330
And so this will then basically give us an array,

202
00:13:13.330 --> 00:13:17.073
which contains all the fields with all the values in there.

203
00:13:18.250 --> 00:13:21.223
So let's then lock that data to the console.

204
00:13:22.140 --> 00:13:25.110
Now let's think what we actually want to do

205
00:13:25.110 --> 00:13:27.340
with this data eventually.

206
00:13:27.340 --> 00:13:30.230
So this data right here is the data

207
00:13:30.230 --> 00:13:33.430
that we eventually will want to use to upload

208
00:13:33.430 --> 00:13:36.470
to the API, right?

209
00:13:36.470 --> 00:13:39.750
And that action of uploading the data is going

210
00:13:39.750 --> 00:13:43.640
to be just another API call, right?

211
00:13:43.640 --> 00:13:46.820
And where do API calls happen?

212
00:13:46.820 --> 00:13:48.912
Well, they happen in the model.

213
00:13:48.912 --> 00:13:51.880
And so therefore we will need a way of getting

214
00:13:51.880 --> 00:13:53.950
this data to the model.

215
00:13:53.950 --> 00:13:56.197
So just like we did many times before,

216
00:13:56.197 --> 00:13:59.028
we now need to create a controller function,

217
00:13:59.028 --> 00:14:04.028
which will then be the handler of this event, okay?

218
00:14:05.460 --> 00:14:10.460
So let's come down here and create controlAddRecipe.

219
00:14:17.290 --> 00:14:20.770
And so this function here will then actually

220
00:14:20.770 --> 00:14:23.003
receive the new recipe data.

221
00:14:26.340 --> 00:14:29.080
And let's actually have this one here

222
00:14:29.080 --> 00:14:30.923
lock the data to the console.

223
00:14:32.230 --> 00:14:36.410
So newRecipe, okay?

224
00:14:36.410 --> 00:14:39.349
And now all we have to do is to say,

225
00:14:39.349 --> 00:14:44.349
addRecipeView.addHandlerUpload

226
00:14:44.963 --> 00:14:47.280
and then controlAddRecipe.

227
00:14:50.840 --> 00:14:53.815
So this is the publisher subscriber pattern

228
00:14:53.815 --> 00:14:57.000
that we have used many times before.

229
00:14:57.000 --> 00:14:59.696
And so eventually here we will have some function

230
00:14:59.696 --> 00:15:04.696
to then upload the new recipe data, okay?

231
00:15:09.150 --> 00:15:10.870
And so here we now need to accept

232
00:15:10.870 --> 00:15:15.030
this handler function and then we need to call it.

233
00:15:15.030 --> 00:15:17.575
So instead of logging it to the console right here,

234
00:15:17.575 --> 00:15:19.897
we will simply call the handler function

235
00:15:19.897 --> 00:15:24.000
and so this handler function will then for now log it

236
00:15:24.000 --> 00:15:27.890
to the console because again, that handler is now

237
00:15:27.890 --> 00:15:29.800
this controlAddRecipe.

238
00:15:32.580 --> 00:15:36.313
All right, so let's see what happens.

239
00:15:37.580 --> 00:15:41.740
And so that's why I have all of these prefilled data now,

240
00:15:41.740 --> 00:15:43.928
so that we can simply click the upload button

241
00:15:43.928 --> 00:15:47.653
and then get our data down here immediately.

242
00:15:49.100 --> 00:15:51.820
So let's now take a look at the data.

243
00:15:51.820 --> 00:15:56.030
And so since we got that data, it means that everything

244
00:15:56.030 --> 00:15:58.683
is correctly set up, which is great.

245
00:15:59.700 --> 00:16:04.700
And so here we get the array of multiple erase in there.

246
00:16:05.620 --> 00:16:07.722
So basically the entries of this form,

247
00:16:07.722 --> 00:16:12.060
where the first element is always the name of the field

248
00:16:12.060 --> 00:16:14.343
and the second one is the value.

249
00:16:16.410 --> 00:16:20.500
All right, so title, source URL,

250
00:16:20.500 --> 00:16:25.290
and you see all of them here, okay?

251
00:16:25.290 --> 00:16:29.320
Now usually, our recipe data is always an object

252
00:16:29.320 --> 00:16:32.380
and not an array of entries like this.

253
00:16:32.380 --> 00:16:36.430
And so in JavaScript, since IES 2019,

254
00:16:36.430 --> 00:16:39.890
there is now a new and very handy method that

255
00:16:39.890 --> 00:16:43.283
we can use to convert entries to an object.

256
00:16:44.430 --> 00:16:47.200
So let's actually call this one here, dataArray.

257
00:16:49.422 --> 00:16:53.333
And then the data itself is gonna be object.fromEntries

258
00:16:57.990 --> 00:16:59.963
and then the data array.

259
00:17:00.840 --> 00:17:03.129
And so this fromEntries method here

260
00:17:03.129 --> 00:17:06.634
is basically the opposite of the entries method

261
00:17:06.634 --> 00:17:10.020
that is available on erase, right?

262
00:17:10.020 --> 00:17:12.930
So this one takes an array of entries

263
00:17:12.930 --> 00:17:15.610
and converts it to an object.

264
00:17:15.610 --> 00:17:18.169
So let's see what that looks like in practice

265
00:17:18.169 --> 00:17:22.924
and beautiful, so this looks already a lot more

266
00:17:22.924 --> 00:17:25.940
like our original recipe object,

267
00:17:25.940 --> 00:17:28.280
like this one here for example,

268
00:17:28.280 --> 00:17:31.359
it is of course still missing some formatting

269
00:17:31.359 --> 00:17:34.950
and it is still missing some data like the ID,

270
00:17:34.950 --> 00:17:37.344
but that we will take care of in the model.

271
00:17:37.344 --> 00:17:40.923
And so let's go do that in the next video.

