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.

