1
00:00:02,100 --> 00:00:04,810
So let's now send that Ajax request

2
00:00:04,810 --> 00:00:08,740
that will trigger the updateItemController action.

3
00:00:08,740 --> 00:00:11,530
For this, we want to wire up this update button here

4
00:00:11,530 --> 00:00:14,470
with a JavaScript event listener,

5
00:00:14,470 --> 00:00:16,520
and for this of course, we first of all need

6
00:00:16,520 --> 00:00:20,090
a JavaScript file that's executed in the browser.

7
00:00:20,090 --> 00:00:25,090
And I'll name that file cart-item-management.js,

8
00:00:25,490 --> 00:00:27,860
not to be confused with cart-management,

9
00:00:27,860 --> 00:00:30,130
which was responsible for adding items

10
00:00:30,130 --> 00:00:32,840
from inside the product detail pages.

11
00:00:32,840 --> 00:00:35,970
Now I have this new file for managing the items

12
00:00:35,970 --> 00:00:38,750
that are already in the cart,

13
00:00:38,750 --> 00:00:43,430
and I want to include that in my cart.ejs file.

14
00:00:43,430 --> 00:00:47,480
Here at the top after including the cart.css file,

15
00:00:47,480 --> 00:00:49,950
I'll add a script and include

16
00:00:49,950 --> 00:00:54,950
/scripts/cart-item-management.js,

17
00:00:55,540 --> 00:00:58,510
and of course, add defer to make sure

18
00:00:58,510 --> 00:01:01,933
that we only execute this once everything has been parsed.

19
00:01:03,920 --> 00:01:05,120
Now, once we're here already,

20
00:01:05,120 --> 00:01:08,680
let's take a look at cart-item.ejs and have a look

21
00:01:08,680 --> 00:01:11,520
at the button at which we want to add a listener.

22
00:01:11,520 --> 00:01:14,237
And actually here I'll change things a little bit.

23
00:01:14,237 --> 00:01:17,340
Instead of just adding a listener to the button,

24
00:01:17,340 --> 00:01:19,540
I'll turn this dev into a form

25
00:01:19,540 --> 00:01:22,200
because it's not a bad idea to include

26
00:01:22,200 --> 00:01:25,130
an input button combination in a form anyways,

27
00:01:25,130 --> 00:01:27,330
for semantic reasons.

28
00:01:27,330 --> 00:01:30,620
And instead of listening for a click on the button

29
00:01:30,620 --> 00:01:33,323
I want to listen for the submission of that form.

30
00:01:34,580 --> 00:01:36,630
Now then once the form is submitted,

31
00:01:36,630 --> 00:01:38,870
I'll need to get access to this input here

32
00:01:38,870 --> 00:01:41,140
and to the data that was entered there,

33
00:01:41,140 --> 00:01:42,913
but we'll do this in a second step.

34
00:01:43,800 --> 00:01:46,720
First of all, let's get access to this form here,

35
00:01:46,720 --> 00:01:48,213
and for this let's not forget

36
00:01:48,213 --> 00:01:52,250
that we've got this form more than once on the same page.

37
00:01:52,250 --> 00:01:54,493
Every cart item has its own form.

38
00:01:55,330 --> 00:01:58,000
Therefore I want to get access to all those forms

39
00:01:58,000 --> 00:02:00,990
that have the cart-item-management clause on them,

40
00:02:00,990 --> 00:02:03,360
and then I want to add submit event listeners

41
00:02:03,360 --> 00:02:05,043
to all those forms.

42
00:02:06,320 --> 00:02:09,889
Hence in the cart-item-management.js file,

43
00:02:09,889 --> 00:02:13,593
we can get access to the cartItemUpdateFormElements

44
00:02:15,670 --> 00:02:17,370
by using document.querySelectorAll

45
00:02:18,510 --> 00:02:20,789
to select all matching elements,

46
00:02:20,789 --> 00:02:25,650
and by then looking for the cart-item-management.css clause

47
00:02:25,650 --> 00:02:29,663
with this CSS selector that's passed to querySelectorAll.

48
00:02:32,249 --> 00:02:36,340
Then we can go through all these formElements,

49
00:02:36,340 --> 00:02:39,490
so through all the cartItemUpdateFormElements,

50
00:02:39,490 --> 00:02:42,050
for example with a four off loop,

51
00:02:42,050 --> 00:02:46,880
and then add an event listener with addEeventListener

52
00:02:46,880 --> 00:02:49,410
and listen to the submit event.

53
00:02:49,410 --> 00:02:51,170
That's the goal here.

54
00:02:51,170 --> 00:02:53,410
And that there is such a submit event built

55
00:02:53,410 --> 00:02:56,350
into the browser, it will be triggered, guess what,

56
00:02:56,350 --> 00:02:58,140
whenever that form is submitted

57
00:02:58,140 --> 00:03:00,133
by clicking a button in the form.

58
00:03:01,710 --> 00:03:03,510
Now we need a function that executes

59
00:03:03,510 --> 00:03:05,140
when that form is submitted,

60
00:03:05,140 --> 00:03:07,830
and I'll name this function updateCartItem

61
00:03:07,830 --> 00:03:09,463
because that is what it'll do.

62
00:03:11,490 --> 00:03:13,940
Now of course, since we use a form

63
00:03:13,940 --> 00:03:17,460
in cart-item.ejs, we could of course always just

64
00:03:17,460 --> 00:03:21,310
set the action and the method attributes there

65
00:03:21,310 --> 00:03:24,390
and let the browser handle the form submission for us,

66
00:03:24,390 --> 00:03:27,200
but I don't want to let the browser do that.

67
00:03:27,200 --> 00:03:28,860
Instead I want to send my own

68
00:03:28,860 --> 00:03:31,580
JavaScripted driven HTTP request

69
00:03:31,580 --> 00:03:34,270
so that we don't force a page reload.

70
00:03:34,270 --> 00:03:35,760
Instead we stay on the page

71
00:03:35,760 --> 00:03:38,610
and just update the parts that changed,

72
00:03:38,610 --> 00:03:42,340
and so that we can also send a patch HTTP request,

73
00:03:42,340 --> 00:03:44,620
which otherwise wouldn't be possible

74
00:03:44,620 --> 00:03:48,330
since forms by default, if the browser supports them for us,

75
00:03:48,330 --> 00:03:51,763
only support get and post HTTP requests.

76
00:03:53,150 --> 00:03:55,750
So that's why I want to handle it myself.

77
00:03:55,750 --> 00:04:00,120
And the implication of that is that here in updateCartItem

78
00:04:00,120 --> 00:04:02,930
in the cart-item-management.js file,

79
00:04:02,930 --> 00:04:06,093
I first of all have to prevent the browser default.

80
00:04:07,000 --> 00:04:08,300
We can do this with help

81
00:04:08,300 --> 00:04:12,090
of the automatically generated end-provided event object

82
00:04:12,090 --> 00:04:16,800
which we get here by then calling event.preventDefault.

83
00:04:16,800 --> 00:04:18,649
With that, we prevent the default

84
00:04:18,649 --> 00:04:22,029
of the browser automatically sending some kind of request,

85
00:04:22,029 --> 00:04:23,313
which we don't want here.

86
00:04:24,590 --> 00:04:26,400
We of course also have to connect

87
00:04:26,400 --> 00:04:27,740
the addEventListener method for the submit event

88
00:04:29,310 --> 00:04:32,560
to the updateCartItem function we just added,

89
00:04:32,560 --> 00:04:33,393
like this.

90
00:04:34,830 --> 00:04:36,750
Now we are in that function

91
00:04:36,750 --> 00:04:39,380
for a certain form that was submitted,

92
00:04:39,380 --> 00:04:42,820
and now of course we need to get access

93
00:04:42,820 --> 00:04:46,913
to more details about which items should be updated.

94
00:04:47,810 --> 00:04:50,172
To be precise, we need the product ID

95
00:04:50,172 --> 00:04:52,230
of the item that should be updated

96
00:04:52,230 --> 00:04:54,010
because the product ID allows us

97
00:04:54,010 --> 00:04:57,090
to uniquely identify a single cart item,

98
00:04:57,090 --> 00:05:00,071
since we have one cart item per product,

99
00:05:00,071 --> 00:05:03,329
and we of course need to know which quantity

100
00:05:03,329 --> 00:05:04,910
we want to use in the future,

101
00:05:04,910 --> 00:05:07,163
so the new quantity that was entered.

102
00:05:08,450 --> 00:05:13,340
So for this, we need the productId and we can get that

103
00:05:13,340 --> 00:05:17,050
as we did it before, by going to cart-item.ejs

104
00:05:17,050 --> 00:05:20,510
and simply adding this as a data- attribute

105
00:05:20,510 --> 00:05:22,540
to the elements that causes the event,

106
00:05:22,540 --> 00:05:23,823
in this case the form.

107
00:05:24,840 --> 00:05:28,800
Here we can add productid and then simply output

108
00:05:29,800 --> 00:05:32,773
item.product.id like this.

109
00:05:34,820 --> 00:05:36,710
Then we can access this.

110
00:05:36,710 --> 00:05:39,360
We also can already add the csrf token

111
00:05:39,360 --> 00:05:41,380
because we'll need that as well.

112
00:05:41,380 --> 00:05:44,773
So I'll add a data-csrf field here,

113
00:05:46,800 --> 00:05:49,683
and then here, output locals.csrfToken,

114
00:05:52,520 --> 00:05:56,250
and then back in our JavaScript file,

115
00:05:56,250 --> 00:05:58,610
in the cart-item-management file,

116
00:05:58,610 --> 00:06:02,990
here we can get access to the form

117
00:06:04,310 --> 00:06:06,520
by accessing event.target,

118
00:06:06,520 --> 00:06:08,720
because that's the thing that causes event,

119
00:06:08,720 --> 00:06:10,880
the form that was submitted.

120
00:06:10,880 --> 00:06:13,170
And on that form we can access the data set

121
00:06:13,170 --> 00:06:18,170
and get access to the productid, with a lowercase "i" here,

122
00:06:18,620 --> 00:06:23,290
because I chose a lowercase "i" in the cart-item.ejs file

123
00:06:23,290 --> 00:06:25,303
for data-productID here.

124
00:06:27,120 --> 00:06:30,830
And of course, we also want to get the csrf token already,

125
00:06:30,830 --> 00:06:34,750
so that is then accessed with help of form.dataset.csrf,

126
00:06:37,460 --> 00:06:40,230
not csrfToken, just csrf-

127
00:06:40,230 --> 00:06:43,980
that was the identifier I added as a data attribute-

128
00:06:43,980 --> 00:06:46,170
and of course we need to know the quantity,

129
00:06:46,170 --> 00:06:50,190
the new quantity or the quantity in general

130
00:06:50,190 --> 00:06:52,120
for that item that should be set,

131
00:06:52,120 --> 00:06:55,540
and we get that from the input element

132
00:06:55,540 --> 00:06:57,373
that we have in this form.

133
00:06:58,520 --> 00:07:00,040
Now if we have a look at this form,

134
00:07:00,040 --> 00:07:03,850
we see that the input element is the first element in there.

135
00:07:03,850 --> 00:07:07,260
So we can do a little bit of DOM traversal to get hold of it

136
00:07:07,260 --> 00:07:10,150
since we already have access to the form.

137
00:07:10,150 --> 00:07:12,400
So the quantity can then be extracted

138
00:07:12,400 --> 00:07:15,503
by accessing form.firstElementChild.value.

139
00:07:21,373 --> 00:07:23,830
The first element child will be the input

140
00:07:23,830 --> 00:07:27,380
and every input Dom element has a value property

141
00:07:27,380 --> 00:07:30,253
that holds the value that was entered by the user.

142
00:07:31,680 --> 00:07:34,490
Now we've got all the data we need to send the request

143
00:07:34,490 --> 00:07:37,390
and therefore now we can again use the fetch function

144
00:07:37,390 --> 00:07:41,050
to send the request to /cart/items

145
00:07:42,130 --> 00:07:44,803
because that was this route which I defined here.

146
00:07:46,030 --> 00:07:48,510
Now it's a patch request which I want to send,

147
00:07:48,510 --> 00:07:51,510
so therefore for this configuration object,

148
00:07:51,510 --> 00:07:53,470
which we pass to fetch,

149
00:07:53,470 --> 00:07:56,200
we set the method to PATCH

150
00:07:57,330 --> 00:07:59,660
and we now need to add a body

151
00:07:59,660 --> 00:08:01,780
and that needs to be in JSON format

152
00:08:01,780 --> 00:08:04,870
just as we used it before for the post request.

153
00:08:04,870 --> 00:08:08,330
And I'll send the object where I have a productId,

154
00:08:08,330 --> 00:08:11,393
which is the productId I extracted up here,

155
00:08:13,010 --> 00:08:15,623
where I add the newQuantity,

156
00:08:16,690 --> 00:08:20,070
which is my quantity constant I have here.

157
00:08:20,070 --> 00:08:22,760
And the keys I set here in this object

158
00:08:22,760 --> 00:08:26,380
should be the keys I'm trying to extract in my controller.

159
00:08:26,380 --> 00:08:27,900
So there in the controller,

160
00:08:27,900 --> 00:08:32,900
I try to extract productId with a capital "I" and quantity,

161
00:08:33,330 --> 00:08:36,880
therefore I have to set those keys in cart-item-management

162
00:08:36,880 --> 00:08:39,360
and therefore this should actually just be quantity

163
00:08:39,360 --> 00:08:40,510
because as we just saw,

164
00:08:40,510 --> 00:08:43,169
I try to extract quantity in the controller,

165
00:08:43,169 --> 00:08:44,733
not newQuantity.

166
00:08:46,290 --> 00:08:49,090
Last but not least for the csrf protection,

167
00:08:49,090 --> 00:08:51,790
we need to add the _csrf field

168
00:08:51,790 --> 00:08:55,133
and set this equal to the csrfToken we get access to.

169
00:08:56,930 --> 00:08:59,890
Now we also need to add some headers-

170
00:08:59,890 --> 00:09:02,400
to be precise, the 'Content-Type' header

171
00:09:02,400 --> 00:09:04,430
so that on the server side

172
00:09:04,430 --> 00:09:08,670
our content is parsed correctly, as explained earlier.

173
00:09:08,670 --> 00:09:11,673
We set the 'Content-Type' to 'application/json' for that.

174
00:09:13,270 --> 00:09:17,010
And then just as before, this of course returns a promise,

175
00:09:17,010 --> 00:09:21,770
so we can use async await here to wait for this response

176
00:09:22,700 --> 00:09:25,500
and store that in an extra constant,

177
00:09:25,500 --> 00:09:26,900
and just as before,

178
00:09:26,900 --> 00:09:30,003
we of course also might want to do some error handling.

179
00:09:31,000 --> 00:09:36,000
We can move this all into a try block here, like this,

180
00:09:36,500 --> 00:09:39,993
and catch any potential errors we might be facing,

181
00:09:40,970 --> 00:09:44,220
in which case I'll just use the alert function

182
00:09:44,220 --> 00:09:47,450
to build in one and say 'Something went wrong!',

183
00:09:48,350 --> 00:09:51,760
and then return so that no other code executes,

184
00:09:51,760 --> 00:09:54,690
and to ensure that we can use the response thereafter,

185
00:09:54,690 --> 00:09:57,810
just as before I'll define it as a separate variable,

186
00:09:57,810 --> 00:09:59,083
which I set in here.

187
00:10:00,110 --> 00:10:02,570
And then therefore, after this try-catch block,

188
00:10:02,570 --> 00:10:06,030
we also want to check if the response is maybe not okay,

189
00:10:06,030 --> 00:10:07,930
so we have no technical problem,

190
00:10:07,930 --> 00:10:10,110
but we have an error status code

191
00:10:10,110 --> 00:10:12,750
that's sent back for example.

192
00:10:12,750 --> 00:10:16,560
In this case I also of course want to do something,

193
00:10:16,560 --> 00:10:20,715
I want to simply, well, do to same as before-

194
00:10:20,715 --> 00:10:22,823
show this alert and return.

195
00:10:24,960 --> 00:10:27,590
After the safe check, we know that the response is okay,

196
00:10:27,590 --> 00:10:29,783
and then we can get the responseData

197
00:10:30,840 --> 00:10:35,083
by awaiting response.json to extract that data,

198
00:10:35,960 --> 00:10:38,260
and then once we got this data,

199
00:10:38,260 --> 00:10:41,453
we can of course update the Dom appropriately.

