1
00:00:01,620 --> 00:00:04,630
All right, let's continue with our server side form validation.

2
00:00:04,650 --> 00:00:11,910
So right now we have this our reservation form, and that actually puts an empty form object in there

3
00:00:11,910 --> 00:00:13,950
that we can use for validation.

4
00:00:14,160 --> 00:00:21,360
And under our code, we under errors, we've defined a type of errors that will hold our errors, which

5
00:00:21,360 --> 00:00:26,910
is a map of type string with every value associated with an index of string being a slice of strings,

6
00:00:26,940 --> 00:00:30,510
because we might have more than one error for a given field in a form.

7
00:00:30,540 --> 00:00:31,610
That's why it's a slice.

8
00:00:32,310 --> 00:00:38,220
We have a function to add errors which will append an error and a message and associated with a particular

9
00:00:38,220 --> 00:00:38,670
field.

10
00:00:39,060 --> 00:00:43,980
And we have a function to check and see if there are errors and return the first error if there is one.

11
00:00:44,220 --> 00:00:47,070
OK, so that's for that part and other forms.

12
00:00:47,310 --> 00:00:54,090
We have our type that describes the form data that we're going to add errors to if any exist.

13
00:00:54,570 --> 00:00:58,710
And we have new, which allows us to create a new form, a new empty form.

14
00:00:59,380 --> 00:01:03,020
And we have this one check has which isn't finished yet.

15
00:01:03,030 --> 00:01:05,010
And you may have noticed that if you were paying attention.

16
00:01:05,490 --> 00:01:11,640
But let's go through the process of how we actually handle posted form data and perform server side

17
00:01:11,640 --> 00:01:12,260
validation.

18
00:01:12,780 --> 00:01:17,160
So I'm back in my handler's file and I'm looking at that empty function we created last time called

19
00:01:17,160 --> 00:01:18,020
Post Reservation.

20
00:01:18,390 --> 00:01:20,850
What's the very first thing I want to do?

21
00:01:21,060 --> 00:01:22,230
It is good practice.

22
00:01:22,230 --> 00:01:29,100
When you were parsing form data to do this, create a variable called error and assign it a method that's

23
00:01:29,100 --> 00:01:32,780
built on the request called pass form, and that's it.

24
00:01:33,150 --> 00:01:37,230
So you try to parse the form there and if there's an error, you take the user somewhere, you display

25
00:01:37,350 --> 00:01:38,040
whatever it may be.

26
00:01:38,040 --> 00:01:41,910
But all we're going to do right now is to say if error is not equal to nil.

27
00:01:42,030 --> 00:01:47,370
In other words, if there's an error parsing that form form data, then we'll just log it the print

28
00:01:47,370 --> 00:01:50,630
line, log the error and we'll return so they'll get a blank screen.

29
00:01:50,640 --> 00:01:55,590
I'm not going to see anything will make this better later on when we handle errors in a more sophisticated

30
00:01:55,590 --> 00:01:56,000
fashion.

31
00:01:56,940 --> 00:01:58,290
So I pass that form data.

32
00:01:58,680 --> 00:01:59,470
Now what do I do?

33
00:02:00,090 --> 00:02:04,530
Well, think about what we want to do here on my reservation page.

34
00:02:04,530 --> 00:02:09,210
I have four pieces of data, actually five one is the hidden form for the CSF token, but we're not

35
00:02:09,210 --> 00:02:10,200
doing anything with that.

36
00:02:10,200 --> 00:02:14,340
We're just letting our middleware make sure that this form is being posted from a page on our site.

37
00:02:14,610 --> 00:02:19,800
And it's not some malicious user who's written a script to access our forums as many times as he or

38
00:02:19,800 --> 00:02:22,160
she possibly can just because they're nasty.

39
00:02:22,170 --> 00:02:23,610
So we only have four we care about.

40
00:02:23,610 --> 00:02:24,450
We have first name.

41
00:02:24,840 --> 00:02:27,600
We have last name, we have email and we have phone.

42
00:02:27,750 --> 00:02:33,870
Now, I could if I wanted to back in my handler actually create four variables first name, last name,

43
00:02:33,870 --> 00:02:36,810
email and phone and keep track of all of those.

44
00:02:36,960 --> 00:02:38,550
But it's common practice.

45
00:02:38,550 --> 00:02:43,410
When I have data that's, you know, all associated with one another, let's create a new model.

46
00:02:43,410 --> 00:02:46,710
So I'm going to go to my models and I'm going to open.

47
00:02:47,380 --> 00:02:48,780
Let's see what shall I do.

48
00:02:50,250 --> 00:02:51,120
I just put it right here.

49
00:02:51,630 --> 00:02:52,140
Actually, no.

50
00:02:52,140 --> 00:02:57,240
Let's create a new file called Models New Go File, Model Start Go.

51
00:02:57,840 --> 00:03:00,270
Because the name of that one, I will add this.

52
00:03:00,630 --> 00:03:02,190
The name of that one is our template data.

53
00:03:02,220 --> 00:03:03,960
Here's where we're going to store all of our models.

54
00:03:03,960 --> 00:03:08,760
And eventually these models will be used to store things in a database to to get data from a database

55
00:03:08,760 --> 00:03:10,080
and store them in these models.

56
00:03:10,350 --> 00:03:16,860
But right now we're just going to create one and I'll create a model which I will call obviously reservation.

57
00:03:17,130 --> 00:03:26,370
So let's create a type of reservation, which is a struct, and it has one field for each of the kinds

58
00:03:26,370 --> 00:03:27,810
of information I need to store in that.

59
00:03:27,990 --> 00:03:34,470
So first name and I'm going to export it because I want it to be available outside of the models package.

60
00:03:34,650 --> 00:03:40,320
And it's a string and we'll have last name, email and phone, all of which are strings, last name,

61
00:03:41,640 --> 00:03:46,560
email and phone, and I'll give that a nice comment.

62
00:03:48,330 --> 00:03:53,340
Reservation holds the reservation data and I've created that type.

63
00:03:53,790 --> 00:04:00,690
So back in my handlers, let's open this up and let's actually store that data right in a reservation

64
00:04:00,690 --> 00:04:02,100
object, which we just created.

65
00:04:02,700 --> 00:04:09,660
So I'll create a reservation object like this reservation, which is just a variable name, and that's

66
00:04:09,660 --> 00:04:13,020
going to be a type models DOT reservation.

67
00:04:13,380 --> 00:04:18,060
And I'm actually going to populate it with the information that the user posted from the form, even

68
00:04:18,060 --> 00:04:20,090
though it might be bad data, I'm going to save it.

69
00:04:20,490 --> 00:04:27,120
So first name is going to be equal to and how do we get something from a post request are not formed

70
00:04:27,210 --> 00:04:27,540
yet.

71
00:04:27,540 --> 00:04:32,760
And the name that I want, which happens to be first name and then the last name

72
00:04:35,820 --> 00:04:45,270
which is assigned the value of our dot form dot get last name and one for email and for phone.

73
00:04:45,270 --> 00:04:46,230
So I'll just do it this way.

74
00:04:46,530 --> 00:04:51,000
Phone, email, phone

75
00:04:54,840 --> 00:04:55,480
and email.

76
00:04:58,260 --> 00:05:01,140
OK, so now I've populated this reservation.

77
00:05:01,350 --> 00:05:07,200
Variable as a struct of type models reservation, and I've given it all of the appropriate values,

78
00:05:07,710 --> 00:05:12,120
so I've grabbed first name from whatever they entered in the first name field of the form, last name,

79
00:05:12,120 --> 00:05:13,380
phone, email, same thing.

80
00:05:13,410 --> 00:05:14,550
That's all stored here.

81
00:05:14,550 --> 00:05:16,420
And this might be bad data.

82
00:05:17,340 --> 00:05:20,310
So how am I going to now check my form?

83
00:05:20,340 --> 00:05:24,560
Well, we don't have a form object at the moment, but we're going to get one.

84
00:05:24,600 --> 00:05:28,440
We're going to create a new one by creating forms our form, which is our variable.

85
00:05:28,860 --> 00:05:32,440
And we're going to assign that the value of forms new.

86
00:05:32,550 --> 00:05:37,100
And this time, we're not going to parse it until we're going to pass that post for our post four.

87
00:05:38,280 --> 00:05:42,130
So this is what has all those euro values and the associated data.

88
00:05:42,630 --> 00:05:46,530
So this is created by calling forms new right over here.

89
00:05:46,530 --> 00:05:48,780
And all that does is say, OK, get the data.

90
00:05:48,780 --> 00:05:54,750
You just passed me, which happened to be our post form, which is which is of type you are values and

91
00:05:55,200 --> 00:05:57,510
create the foreign object and send back a pointer to it.

92
00:05:57,520 --> 00:05:59,070
So we have that back at our handlers.

93
00:05:59,700 --> 00:06:01,230
We have our form now.

94
00:06:01,230 --> 00:06:02,290
We can actually check things.

95
00:06:02,460 --> 00:06:08,580
So the first thing we have over on forms Dargo is this has is the only thing we have that's not new

96
00:06:08,580 --> 00:06:13,490
or a typed definition we have this one function has and that returns bool.

97
00:06:13,620 --> 00:06:16,980
So let's go back here and you'll see why we don't have enough.

98
00:06:16,990 --> 00:06:20,250
Go back to our handlers and we want to make sure that it's valid.

99
00:06:20,250 --> 00:06:28,110
So I can just say on this form of that created form DOT has, it should have first name and I need to

100
00:06:28,110 --> 00:06:29,220
pass that my request.

101
00:06:29,670 --> 00:06:30,450
So there I've done that.

102
00:06:30,450 --> 00:06:37,560
I've now called form and said, hey, look, does this form have the value first name and is it something

103
00:06:37,560 --> 00:06:38,840
more than an empty string?

104
00:06:38,850 --> 00:06:43,280
We checked the form a post request for the value of first name.

105
00:06:43,290 --> 00:06:48,850
Does it have an entry for first name if it has one and its empty return false otherwise return true.

106
00:06:49,170 --> 00:06:55,500
So when I call this back over and handlers, I'm calling the function has, but I'm not doing anything

107
00:06:55,500 --> 00:06:59,880
with its response, so I probably should make this a little more valid.

108
00:07:00,330 --> 00:07:02,550
I need to check if my form is valid.

109
00:07:02,550 --> 00:07:05,400
It would be great if I could put whatever checks I want here.

110
00:07:05,400 --> 00:07:06,450
As many as I might have.

111
00:07:06,450 --> 00:07:13,470
I might have ten, I might have three and then just say, if not formed valid, do something.

112
00:07:13,560 --> 00:07:16,770
In other words, you failed form validation, but that function doesn't exist yet.

113
00:07:16,800 --> 00:07:17,760
So let's go put it in there.

114
00:07:17,760 --> 00:07:22,530
Let's go to our forms package and let's put in this func.

115
00:07:23,760 --> 00:07:29,610
And it's going to be having the receiver of a verb form so we can look at our form data of type form

116
00:07:31,200 --> 00:07:34,950
valid, and that's going to return a ball.

117
00:07:35,130 --> 00:07:36,360
So I better put my ball in there.

118
00:07:37,470 --> 00:07:42,570
All this, does it say if there are any errors at all associated with the form object F that I'm getting

119
00:07:42,570 --> 00:07:49,950
from my receiver return that the value of of fault, if there are errors and truth, are sorry.

120
00:07:50,130 --> 00:07:54,990
If it's valid, if there are no errors, return true or otherwise return false.

121
00:07:55,020 --> 00:08:03,610
So all I have to do here really is say return the length of errors if that happens to be equal to zero.

122
00:08:03,630 --> 00:08:04,380
It's going to return.

123
00:08:04,380 --> 00:08:04,770
True.

124
00:08:04,800 --> 00:08:06,540
Otherwise it's going to return false.

125
00:08:06,810 --> 00:08:08,730
That's a nice shorthand way of doing it.

126
00:08:08,760 --> 00:08:11,880
I could have written it over four lines and it would work just as well.

127
00:08:12,180 --> 00:08:14,880
But this seems to me to be the simplest approach to do it.

128
00:08:14,890 --> 00:08:15,690
So let's do this.

129
00:08:18,570 --> 00:08:20,490
Valid returns.

130
00:08:21,930 --> 00:08:26,370
True if there are no errors.

131
00:08:26,370 --> 00:08:29,250
In other words, the form is valid, otherwise false.

132
00:08:32,370 --> 00:08:34,310
OK, so that's great.

133
00:08:34,650 --> 00:08:40,020
But the other thing I need to pay attention to is my house check doesn't actually add an error anywhere.

134
00:08:40,020 --> 00:08:41,990
It just checks to see if the field exists.

135
00:08:42,210 --> 00:08:43,170
So we could do this.

136
00:08:43,650 --> 00:08:51,450
We can just go back to here before this return false part and say f dort errors, which is my receiver,

137
00:08:51,450 --> 00:08:56,310
I'm calling the F object and that has a function associated with it called ADD.

138
00:08:56,820 --> 00:09:02,460
And I can add my airstrip and the ad is for the field when I call it with first name that is populated

139
00:09:02,460 --> 00:09:03,870
with the string value of first name.

140
00:09:04,200 --> 00:09:10,080
And I don't need to specify the error message, which can be something as simple as this field cannot

141
00:09:10,080 --> 00:09:10,770
be blank.

142
00:09:11,730 --> 00:09:12,120
All right.

143
00:09:13,110 --> 00:09:16,950
So now when I call this, that actually will add an error to it.

144
00:09:16,950 --> 00:09:18,660
And that's exactly what I wanted to do.

145
00:09:19,860 --> 00:09:25,590
So we have our has we have our new and and our handlers now where you need to keep going.

146
00:09:25,600 --> 00:09:31,320
So if the form is not valid at this point, when I call form has now it's returning a false or true,

147
00:09:31,320 --> 00:09:37,020
which I'm ignoring, but it's also adding an error if first name is empty or nonexistent.

148
00:09:37,980 --> 00:09:46,160
So what I want to do, if the form is actually has a problem on it, well, pretty straightforward.

149
00:09:46,800 --> 00:09:50,940
Let's first of all, create a variable to hold our reservation.

150
00:09:50,940 --> 00:09:57,620
And when we're passing data to a template, remember, we had that value called data.

151
00:09:57,630 --> 00:10:01,790
So if we go over to our template data here, we have this nice one called Where Is It?

152
00:10:01,800 --> 00:10:04,050
Data, which is a map of string interface.

153
00:10:04,320 --> 00:10:07,220
So let's go back to our handlers and create a map of string interface.

154
00:10:07,800 --> 00:10:14,550
So I'll call it data is equal to make a map string interface.

155
00:10:15,990 --> 00:10:21,930
And then I'll add my reservation to that data reservation, which is how I'll look it up on the template

156
00:10:22,020 --> 00:10:23,790
when I need to, which I'm not going to do this lecture.

157
00:10:23,790 --> 00:10:29,710
But we will eventually is equal to the reservation, that object I created up here.

158
00:10:29,730 --> 00:10:31,880
So now I'm storing that in that value.

159
00:10:32,460 --> 00:10:34,380
And now what do I want to do?

160
00:10:34,380 --> 00:10:39,120
If they didn't pass validation, I can't just hand them back to the reservation handler because that's

161
00:10:39,120 --> 00:10:40,080
creating an empty form.

162
00:10:40,080 --> 00:10:42,300
But what I can do is the similar thing.

163
00:10:42,690 --> 00:10:44,850
I can actually render the form right from here.

164
00:10:45,390 --> 00:10:50,430
I can say render that form and I'm going to pass it, not forms new nil.

165
00:10:50,820 --> 00:10:56,040
I'm going to pass it form object I created here, which now has an error associated with it because

166
00:10:56,040 --> 00:11:02,220
I called the has function so I can just pass it forward, let me get rid of this and just put my variable

167
00:11:02,220 --> 00:11:02,700
form there.

168
00:11:02,790 --> 00:11:11,130
And I'm also going to pass it data which holds this reservation map or this map that has a value of

169
00:11:11,130 --> 00:11:11,960
reservation in it.

170
00:11:11,970 --> 00:11:14,550
So now I have the information that the user entered.

171
00:11:14,850 --> 00:11:19,680
I have the errors, if any, generated by this and I render that page.

172
00:11:19,800 --> 00:11:22,620
And at that point I want to stop processing this function.

173
00:11:22,620 --> 00:11:24,340
I don't want to go any further, so I'll just return.

174
00:11:25,440 --> 00:11:25,770
All right.

175
00:11:25,770 --> 00:11:26,820
Let's see what this does.

176
00:11:27,420 --> 00:11:29,220
So far, it's not going to do very much, but let's try it.

177
00:11:29,220 --> 00:11:32,790
Let's make sure it compiles or stop my application and rerun it.

178
00:11:34,830 --> 00:11:40,890
It comp. That's promising, let's go back over to our make reservation page, reload this and try submitting

179
00:11:40,890 --> 00:11:41,010
it.

180
00:11:42,390 --> 00:11:43,260
It took me back.

181
00:11:43,980 --> 00:11:45,170
It didn't do anything.

182
00:11:45,210 --> 00:11:45,780
Why not?

183
00:11:45,780 --> 00:11:48,210
Because I have no logic of my template to display errors.

184
00:11:48,990 --> 00:11:51,290
Well, we can do that if we can do it really easily.

185
00:11:51,300 --> 00:11:55,800
So let's go back over to open up our template, which is the make preservation page.

186
00:11:56,130 --> 00:12:02,790
Hide this window and let's think about how we can actually get access to the reservation object.

187
00:12:02,790 --> 00:12:03,810
Probably not this lecture.

188
00:12:03,820 --> 00:12:09,090
That'll be the next one, but get access to the errors object so we can do that pretty easily.

189
00:12:10,020 --> 00:12:12,380
What I'm going to do is write at the top here.

190
00:12:12,420 --> 00:12:14,460
I'm going to give myself a little bit of space to work.

191
00:12:15,120 --> 00:12:17,130
I'm only working with first name right now.

192
00:12:17,400 --> 00:12:22,440
And what I want to do is to say if there's an error, if there's an error associated with first name,

193
00:12:22,830 --> 00:12:25,740
I want to display something and I'm going to stick it right next to the label.

194
00:12:25,740 --> 00:12:28,980
So when there's an error, I want the error message to display right here.

195
00:12:29,410 --> 00:12:32,190
How am I going to get access to that errors object?

196
00:12:32,220 --> 00:12:38,430
Well, we know that we have a form object, so let's just use the new syntax you haven't seen it with.

197
00:12:38,700 --> 00:12:42,840
And that is a directive for a goal line template in the language, for the structure, for it is very

198
00:12:42,840 --> 00:12:51,870
simple with dot form dot errors, dot get and I'm going to look for the first name, the name of the

199
00:12:51,870 --> 00:12:55,890
field, and that's exactly how I'm storing it in that form object.

200
00:12:56,040 --> 00:13:03,510
I'm storing a string, a map of string, slice of strings and I'm saying with form errors get first

201
00:13:03,510 --> 00:13:09,120
name and this has to have an end like everything else, pretty much everything else and go like templates.

202
00:13:10,230 --> 00:13:16,200
I want to display something I don't want to display a label class equals text danger, which will make

203
00:13:16,200 --> 00:13:16,560
it red.

204
00:13:16,560 --> 00:13:17,760
That's a bootstrap class.

205
00:13:18,000 --> 00:13:24,450
And all I want to display is whatever the value from form errors get first name is.

206
00:13:24,990 --> 00:13:26,400
So I'll just display that.

207
00:13:26,550 --> 00:13:28,140
And that's all I have to do at this point.

208
00:13:28,410 --> 00:13:29,970
But I could do something else.

209
00:13:30,100 --> 00:13:30,840
It would be great.

210
00:13:30,840 --> 00:13:31,950
Let's just try it like this first.

211
00:13:31,950 --> 00:13:40,740
So let me stop the application and go back here, go to the Make Reservation page to make sure I'm starting

212
00:13:40,740 --> 00:13:45,510
with an empty form and click make reservation and it comes back to this form and gives me that error

213
00:13:45,510 --> 00:13:45,900
message.

214
00:13:46,410 --> 00:13:49,350
Be nice if I could make this be outlined in red as well.

215
00:13:49,380 --> 00:13:55,560
Well, it turns out I can't pretty easily and I can do that simply by in the class for the input which

216
00:13:55,560 --> 00:13:57,330
is right here.

217
00:13:57,570 --> 00:14:04,950
I can put more logic in there as well with DOT form, which is in our template data, part of our default

218
00:14:05,160 --> 00:14:07,440
default data and handed to us by the handler.

219
00:14:07,440 --> 00:14:13,740
When the form fails, validation errors don't get first name.

220
00:14:14,220 --> 00:14:19,830
So if that returns true, if there is more than one error, if there's a value stored informed, our

221
00:14:19,830 --> 00:14:23,850
errors don't get first name that map, string, slice of strings.

222
00:14:24,030 --> 00:14:24,930
What do I want to do?

223
00:14:25,050 --> 00:14:31,440
Well, all I want to do is add a class and the class is a bootstrap class called is invalid.

224
00:14:32,010 --> 00:14:33,660
And then of course I have to have my hand.

225
00:14:34,710 --> 00:14:39,660
Now if I do that and I'll put this down on the next line so it's organized a little better, I should

226
00:14:39,660 --> 00:14:45,540
be able to just run this because we're rebuilding our template cash in every request and it should make

227
00:14:45,810 --> 00:14:49,110
this box outlined in red and it failed.

228
00:14:49,260 --> 00:14:50,180
What did I get wrong?

229
00:14:50,190 --> 00:14:52,620
Let's go back here with format errors.

230
00:14:52,620 --> 00:14:56,820
Don't get first name is invalid and OK.

231
00:14:57,360 --> 00:14:58,170
Oh, there it is.

232
00:14:58,170 --> 00:14:58,320
Right.

233
00:14:58,320 --> 00:15:04,490
There is a quotation mark has to be on the outside, otherwise it's invalid html.

234
00:15:04,500 --> 00:15:10,350
So I have an opening class tag right here, but I never have a closing class tag or quote for that,

235
00:15:10,350 --> 00:15:14,130
so it never ends and go fortunately is extremely picky about that.

236
00:15:14,130 --> 00:15:16,630
So let's try this again now.

237
00:15:16,630 --> 00:15:18,720
It'll work and it does.

238
00:15:18,750 --> 00:15:23,460
It gives me the nice little thing right here, the little exclamation mark, it outlines this in red

239
00:15:23,460 --> 00:15:24,570
and it has an error message.

240
00:15:24,990 --> 00:15:25,320
All right.

241
00:15:25,320 --> 00:15:27,900
So that's how we can do some basic validation.

242
00:15:28,200 --> 00:15:30,240
But there are some problems associated with this.

243
00:15:30,240 --> 00:15:40,050
For example, I have for required fields and with my current approach back over here under my handlers

244
00:15:40,050 --> 00:15:43,800
right here, I would have to let me just hide this.

245
00:15:44,160 --> 00:15:49,320
I would have to do form has first name, form has last name, form has email.

246
00:15:49,500 --> 00:15:51,120
That seems really inefficient.

247
00:15:51,450 --> 00:15:56,400
It would be better if I could have, say, a different function or maybe modify this function something

248
00:15:56,400 --> 00:16:00,630
anyway where I could just pass it on any number of required fields.

249
00:16:00,900 --> 00:16:06,240
And if any of those fields are not required, it generates an error for that specific field.

250
00:16:07,050 --> 00:16:08,460
Well, there has to be a way to do that.

251
00:16:08,460 --> 00:16:10,740
And it turns out there is and we'll do that.

252
00:16:11,250 --> 00:16:15,180
And we'll also get around repopulating our form data with whatever they entered here.

253
00:16:15,180 --> 00:16:23,310
Because right now, if I put Smith and John at Smith DOT, CAA or whatever and and submit the form,

254
00:16:24,000 --> 00:16:28,710
I still lose that data, which seems kind of goofy because I've already got it stored in the reservation.

255
00:16:28,710 --> 00:16:30,330
There must be a better way of doing this.

256
00:16:30,330 --> 00:16:31,020
And in fact there is.

257
00:16:31,170 --> 00:16:33,180
And we'll take care of that in the next lecture.
