1 00:00:00,000 --> 00:00:02,220 Instructor: In the last section, we spoke a little bit 2 00:00:02,220 --> 00:00:06,930 about the validation helper, inside of reduxForm. 3 00:00:06,930 --> 00:00:07,763 Remember, all we have 4 00:00:07,763 --> 00:00:10,410 to do is create a new function called Validate, 5 00:00:10,410 --> 00:00:12,570 we'll pass it to the reduxForm helper, 6 00:00:12,570 --> 00:00:15,090 and then whenever a user makes a change to the form, 7 00:00:15,090 --> 00:00:16,224 or tries to submit the form, 8 00:00:16,224 --> 00:00:18,750 our validate function will be called. 9 00:00:18,750 --> 00:00:20,190 Let's see what this looks like in practice, 10 00:00:20,190 --> 00:00:22,500 and I think it'll help with the understanding. 11 00:00:22,500 --> 00:00:26,523 So the first thing we'll do is create our function validate. 12 00:00:27,600 --> 00:00:30,030 Now remember, like I said, the validate function is going 13 00:00:30,030 --> 00:00:32,820 to be called with all the properties of our form, 14 00:00:32,820 --> 00:00:34,635 so all their field names 15 00:00:34,635 --> 00:00:37,020 and the values of the fields as well. 16 00:00:37,020 --> 00:00:40,113 So I'm going to call this argument just formProps. 17 00:00:42,300 --> 00:00:44,580 The first thing we do inside any validate function, 18 00:00:44,580 --> 00:00:47,280 is we make a new object called errors. 19 00:00:47,280 --> 00:00:49,200 And so this is going to be the new object that's gonna 20 00:00:49,200 --> 00:00:51,870 contain any errors that our fields might 21 00:00:51,870 --> 00:00:53,760 be containing right now. 22 00:00:53,760 --> 00:00:54,660 By default, 23 00:00:54,660 --> 00:00:58,920 we always want to simply return our error's object. 24 00:00:58,920 --> 00:01:01,890 Even if it ends up not adding any fields on here, 25 00:01:01,890 --> 00:01:04,800 if we don't add any error messages whatsoever to the user, 26 00:01:04,800 --> 00:01:07,560 we always just end up returning an empty object here, 27 00:01:07,560 --> 00:01:09,450 saying hey, there, you know, here's an empty object. 28 00:01:09,450 --> 00:01:10,465 There were no errors. 29 00:01:10,465 --> 00:01:12,873 Go ahead and submit the form if you like. 30 00:01:14,160 --> 00:01:17,100 So, before we go any further, let's add a console.log, 31 00:01:17,100 --> 00:01:18,660 and just look at the formProps, 32 00:01:18,660 --> 00:01:19,920 and kind of see what they look like, 33 00:01:19,920 --> 00:01:22,620 and what's happening behind the scenes. 34 00:01:22,620 --> 00:01:23,820 One last thing before we test this 35 00:01:23,820 --> 00:01:24,780 out in the browser though, 36 00:01:24,780 --> 00:01:26,160 we have tell reduxForm 37 00:01:26,160 --> 00:01:28,920 to actually use this validate function. 38 00:01:28,920 --> 00:01:31,140 To tell reduxForm to use the validate function, 39 00:01:31,140 --> 00:01:33,120 we are just going to add it as another property 40 00:01:33,120 --> 00:01:35,970 to the reduxForm configuration object. 41 00:01:35,970 --> 00:01:38,730 So I'm going to add a comma after fields, 42 00:01:38,730 --> 00:01:41,790 and then we'll add validate: validate. 43 00:01:41,790 --> 00:01:42,900 Now as you might imagine, 44 00:01:42,900 --> 00:01:45,780 we've got identical key and value here, 45 00:01:45,780 --> 00:01:48,510 so we can condense this down with a little bit of ES6, 46 00:01:48,510 --> 00:01:51,123 to simply be validate, like so. 47 00:01:52,050 --> 00:01:53,640 Alright, let's give this a shot in the browser, 48 00:01:53,640 --> 00:01:55,080 and see what it looks like. 49 00:01:55,080 --> 00:01:58,383 I'm going to open up my terminal, use my console. 50 00:02:01,620 --> 00:02:03,123 I'm going to refresh the page, 51 00:02:04,440 --> 00:02:06,300 and you'll see immediately the instant 52 00:02:06,300 --> 00:02:08,550 that our form renders, we get that console log. 53 00:02:08,550 --> 00:02:11,100 Meaning, the instant the form renders, 54 00:02:11,100 --> 00:02:13,830 reduxForm is going to instantly do some validation for us. 55 00:02:13,830 --> 00:02:17,340 It's going to try to validate the form as often as it can. 56 00:02:17,340 --> 00:02:19,320 Now, when I click into the email field, 57 00:02:19,320 --> 00:02:20,820 notice how it console logs again. 58 00:02:20,820 --> 00:02:24,660 Basically, whenever you do just about anything in reduxForm, 59 00:02:24,660 --> 00:02:28,110 it's going to attempt to validate your inputs here. 60 00:02:28,110 --> 00:02:29,250 So, let's start typing. 61 00:02:29,250 --> 00:02:32,850 I'm gonna say test@example.com, 62 00:02:32,850 --> 00:02:35,520 and you'll notice that we've got this email: 63 00:02:35,520 --> 00:02:37,590 test@example.com in here now. 64 00:02:37,590 --> 00:02:39,153 I'll add a password. 65 00:02:40,200 --> 00:02:42,150 Password. 66 00:02:42,150 --> 00:02:45,540 And, sure enough, we've got email: test@example.com, 67 00:02:45,540 --> 00:02:46,592 with a password of password, 68 00:02:46,592 --> 00:02:49,719 and a password confirm of password as well. 69 00:02:49,719 --> 00:02:53,310 So now we can use this information, these kind of formProps, 70 00:02:53,310 --> 00:02:54,930 to do some validation. 71 00:02:54,930 --> 00:02:56,073 Let's give it a shot. 72 00:02:58,170 --> 00:02:59,214 So, remember the rule here, 73 00:02:59,214 --> 00:03:03,120 if a particular field has an error associated with it, 74 00:03:03,120 --> 00:03:07,380 we add a property of the same name to the errors object, 75 00:03:07,380 --> 00:03:09,120 and the value for that property should be 76 00:03:09,120 --> 00:03:11,970 whatever error message we want to show to the user. 77 00:03:11,970 --> 00:03:13,740 So let's do a very simple case here. 78 00:03:13,740 --> 00:03:18,740 We're going to say if formProps.password does not equal 79 00:03:19,379 --> 00:03:22,697 formProps.passwordConfirm, 80 00:03:23,598 --> 00:03:28,410 then I want to add an error message to the errors object. 81 00:03:28,410 --> 00:03:33,410 I want to say errors.password equals Passwords must match. 82 00:03:38,430 --> 00:03:41,520 So let's see what this looks like inside the browser. 83 00:03:41,520 --> 00:03:45,390 I'm gonna refresh, and then I'm gonna start typing, 84 00:03:45,390 --> 00:03:47,426 and you can see that, hey like, ya know, 85 00:03:47,426 --> 00:03:50,250 well is it doing the validation, 86 00:03:50,250 --> 00:03:51,600 we saw the console logs before, 87 00:03:51,600 --> 00:03:53,340 but where's the error message? 88 00:03:53,340 --> 00:03:54,388 So that's kind of the key here. 89 00:03:54,388 --> 00:03:57,330 reduxForm makes it easy for us to kind of hook in 90 00:03:57,330 --> 00:03:58,920 and do validation, but it's not, 91 00:03:58,920 --> 00:04:00,720 it doesn't have any magic associated with it 92 00:04:00,720 --> 00:04:03,930 that's going to kind of automatically show errors for us. 93 00:04:03,930 --> 00:04:08,310 So, once we have done this validation, the errors are there, 94 00:04:08,310 --> 00:04:09,990 they're in memory, you know, they're being tracked, 95 00:04:09,990 --> 00:04:11,379 validation is happening, but we have 96 00:04:11,379 --> 00:04:15,570 to actually show some component on the screen, 97 00:04:15,570 --> 00:04:18,029 or some text on the screen, a little bit more manually, 98 00:04:18,029 --> 00:04:21,660 to say, hey here is what the error message actually is. 99 00:04:21,660 --> 00:04:23,110 So let's give a shot at that. 100 00:04:24,510 --> 00:04:26,630 Back over inside of our form, I'm going 101 00:04:26,630 --> 00:04:29,850 to find the password field right here, 102 00:04:29,850 --> 00:04:32,310 and right underneath it, 103 00:04:32,310 --> 00:04:34,749 so I've password label, password input, 104 00:04:34,749 --> 00:04:39,143 I'm going to put curly braces, and then, I'm going to say, 105 00:04:39,143 --> 00:04:44,143 inside of these curly braces, I want to put field.error. 106 00:04:44,160 --> 00:04:48,600 Excuse me, password.error. 107 00:04:48,600 --> 00:04:51,090 So remember, this password right here, is a reference 108 00:04:51,090 --> 00:04:53,463 to the password helper coming from reduxForm. 109 00:04:54,510 --> 00:04:57,420 Whenever we return an error on that errors object, 110 00:04:57,420 --> 00:04:59,190 it's going to be automatically assigned 111 00:04:59,190 --> 00:05:02,580 to the error property of the individual field. 112 00:05:02,580 --> 00:05:05,700 So now let's see what this looks like inside the browser. 113 00:05:05,700 --> 00:05:09,180 I'm gonna refresh the page, and then I'm gonna start typing 114 00:05:09,180 --> 00:05:10,800 in here and you'll see instantly, 115 00:05:10,800 --> 00:05:13,590 I get passwords do not match, er, excuse me, 116 00:05:13,590 --> 00:05:15,390 passwords must match. 117 00:05:15,390 --> 00:05:18,300 So let's trying to, I'm going to put in a password of 123, 118 00:05:18,300 --> 00:05:21,150 and then for confirm password, I'm can put in 123 as well, 119 00:05:21,150 --> 00:05:22,980 and then you can see that error message goes 120 00:05:22,980 --> 00:05:24,750 away automatically. 121 00:05:24,750 --> 00:05:25,800 So this definitely works, ya know, 122 00:05:25,800 --> 00:05:27,240 we're definitely getting the validation here. 123 00:05:27,240 --> 00:05:29,232 As soon as my form becomes invalid, 124 00:05:29,232 --> 00:05:31,473 I get the error message popping back up. 125 00:05:32,670 --> 00:05:34,950 One thing that's really annoying for our users though, 126 00:05:34,950 --> 00:05:37,410 is that the instant they click in and start typing, 127 00:05:37,410 --> 00:05:39,060 they're getting this error message. 128 00:05:39,060 --> 00:05:40,410 And it's kind of like, okay, well hey, 129 00:05:40,410 --> 00:05:42,240 I'm not done typing yet, I haven't actually filled 130 00:05:42,240 --> 00:05:43,767 out the form, why don't you just hold on for a second, 131 00:05:43,767 --> 00:05:45,963 and then you can do the validation. 132 00:05:47,130 --> 00:05:49,650 So to handle that case, or to kind of delay, 133 00:05:49,650 --> 00:05:51,333 showing a message to our user, 134 00:05:52,200 --> 00:05:55,020 we can add in another little helper here, 135 00:05:55,020 --> 00:05:56,070 kind of a little trick. 136 00:05:56,070 --> 00:05:57,750 Let's put the code down for it and then we'll talk 137 00:05:57,750 --> 00:05:59,730 about exactly what's going on. 138 00:05:59,730 --> 00:06:02,430 So right before the password.error, I'm going to put 139 00:06:02,430 --> 00:06:06,700 in password.touched &&, excuse me, && 140 00:06:11,484 --> 00:06:16,484 and then, a div with className of error, and password.error. 141 00:06:21,930 --> 00:06:24,060 So I did a pretty good amount of coding here. 142 00:06:24,060 --> 00:06:29,060 First I put in password.touched && password.error &&, 143 00:06:29,070 --> 00:06:32,400 and then a div with className error, 144 00:06:32,400 --> 00:06:35,343 and it contains the text password.error. 145 00:06:36,180 --> 00:06:38,040 So before we talk about exactly what this code is doing, 146 00:06:38,040 --> 00:06:41,700 let's test out in the browser, and just see what happens. 147 00:06:41,700 --> 00:06:45,720 I'm gonna refresh the page, and now, when I start typing, 148 00:06:45,720 --> 00:06:48,060 you'll notice that I don't immediately get any error message 149 00:06:48,060 --> 00:06:49,770 popping up on the screen, which is definitely good, 150 00:06:49,770 --> 00:06:51,120 just what I want. 151 00:06:51,120 --> 00:06:54,243 Only when I actually click out of the component, 152 00:06:56,130 --> 00:06:58,020 do I see the error message pop up. 153 00:06:58,020 --> 00:06:59,760 So only when I actually click out, 154 00:06:59,760 --> 00:07:01,680 does the error message start to pickup. 155 00:07:01,680 --> 00:07:02,580 Let's refresh. 156 00:07:02,580 --> 00:07:04,470 So I just refreshed the page. 157 00:07:04,470 --> 00:07:05,550 I'm typing in again. 158 00:07:05,550 --> 00:07:06,383 I don't get the error message 159 00:07:06,383 --> 00:07:09,960 until I actually click out of the input field, 160 00:07:09,960 --> 00:07:12,570 and then I see Passwords must match here. 161 00:07:12,570 --> 00:07:14,490 So that's a little bit more of the behavior that I like, 162 00:07:14,490 --> 00:07:16,890 but let's talk about exactly how we achieved it. 163 00:07:18,870 --> 00:07:19,890 So, here's what's happening. 164 00:07:19,890 --> 00:07:23,610 We've got this kind of multi-layer && statement here. 165 00:07:23,610 --> 00:07:25,710 This is a little bit of a trick in JavaScript, 166 00:07:25,710 --> 00:07:28,982 and it basically says, if this evaluates to true, 167 00:07:28,982 --> 00:07:33,982 and this evaluates to true, and this evaluates to true, 168 00:07:34,050 --> 00:07:36,330 then return the last value. 169 00:07:36,330 --> 00:07:37,890 So that's what's happening here. 170 00:07:37,890 --> 00:07:39,570 We're using a little bit of a JavaScript trick 171 00:07:39,570 --> 00:07:42,930 with how it hands these Boolean operators. 172 00:07:42,930 --> 00:07:46,110 So if the password field has been touched by the user, 173 00:07:46,110 --> 00:07:48,402 in other words, if the user has clicked into the field, 174 00:07:48,402 --> 00:07:53,402 and then clicked out, and that field has an error, 175 00:07:54,030 --> 00:07:58,080 then return this div with a className of error 176 00:07:58,080 --> 00:08:00,303 and text of password.error. 177 00:08:01,200 --> 00:08:02,190 So that's giving us a little bit more 178 00:08:02,190 --> 00:08:03,720 of the behavior we actually want here. 179 00:08:03,720 --> 00:08:06,090 Only when the user clicks into the field, 180 00:08:06,090 --> 00:08:08,850 and then clicks out, and there's an error, 181 00:08:08,850 --> 00:08:11,820 then we want to show a div, that has an error message, 182 00:08:11,820 --> 00:08:12,753 to our user. 183 00:08:13,980 --> 00:08:15,960 There is one last little thing here, 184 00:08:15,960 --> 00:08:17,880 I ended on a className of error here, 185 00:08:17,880 --> 00:08:19,720 but you'll notice that our, excuse me, 186 00:08:19,720 --> 00:08:22,680 you'll notice that the text we get is still black here, 187 00:08:22,680 --> 00:08:24,420 and we should really show it as red to our users, 188 00:08:24,420 --> 00:08:26,190 just to kind of indicate to them, hey like, 189 00:08:26,190 --> 00:08:29,280 there's an error here, you need to take care of this. 190 00:08:29,280 --> 00:08:31,530 So to do that, we're just gonna add on a little bit 191 00:08:31,530 --> 00:08:33,390 of custom CSS. 192 00:08:33,390 --> 00:08:35,159 Inside of our project directory, 193 00:08:35,159 --> 00:08:37,020 I'm gonna find the style folder, 194 00:08:37,020 --> 00:08:39,332 and I'm gonna open style.css. 195 00:08:40,500 --> 00:08:41,332 Then inside of here, 196 00:08:41,332 --> 00:08:42,828 we're just gonna add a very simple rule, 197 00:08:42,828 --> 00:08:47,550 just says .error, color: red. 198 00:08:50,190 --> 00:08:53,130 So now, let's give this a shot in the browser. 199 00:08:53,130 --> 00:08:56,340 And if I put it in, now I've got nice red text, 200 00:08:56,340 --> 00:08:58,110 to kind of tell the user, hey, 201 00:08:58,110 --> 00:09:01,140 this thing is currently incorrect, or there's an error 202 00:09:01,140 --> 00:09:01,973 with this field. 203 00:09:01,973 --> 00:09:03,030 You should probably take care of this 204 00:09:03,030 --> 00:09:04,290 before you try to move on. 205 00:09:04,290 --> 00:09:05,310 So this is definitely a little bit more 206 00:09:05,310 --> 00:09:08,550 of what our users expect to see here. 207 00:09:08,550 --> 00:09:09,840 So this is looking pretty good. 208 00:09:09,840 --> 00:09:11,831 Once we put in some text, it gets validated, 209 00:09:11,831 --> 00:09:15,240 and then when it actually matches, the error goes away, 210 00:09:15,240 --> 00:09:17,190 which is just what we expect. 211 00:09:17,190 --> 00:09:19,200 Let's continue in the next section, where we'll add 212 00:09:19,200 --> 00:09:21,450 in some more validation around just discerning 213 00:09:21,450 --> 00:09:25,740 that an email and a password combination exists at all. 214 00:09:25,740 --> 00:09:27,833 So let's take care of that in the next section.