WEBVTT

00:00.000 --> 00:05.220
Okay, so let's take a look at what we have here and see how we can make this more reusable, not just

00:05.220 --> 00:10.020
for our text field, but for things like our description field as well where we have multiple rows.

00:10.020 --> 00:19.320
Our text field does take a multi-line property, so we can very easily convert this into a text area

00:19.350 --> 00:20.790
type of input.

00:21.630 --> 00:23.520
And we'll take a look at how we can achieve that.

00:23.520 --> 00:31.590
So inside the app folder where we've got our shared folder and components, let's create another component

00:31.590 --> 00:41.520
inside here I'll say new file and call it app text inputs X.

00:41.940 --> 00:46.170
And then inside here we'll create the boilerplate we need as per normal.

00:46.170 --> 00:52.650
And inside here we can use another react hook so that we can get hold of the controller properties.

00:52.920 --> 01:02.070
So inside here we'll say const and then equals use controller Which is the hook version of what we're

01:02.070 --> 01:03.840
using inside our component.

01:03.840 --> 01:05.970
And we need to pass this some properties.

01:05.970 --> 01:12.000
And if we hover over this it's expecting an argument and it needs some props.

01:12.000 --> 01:14.010
So we'll create some props for this.

01:14.010 --> 01:19.770
And up here I'll specify type props equals.

01:21.540 --> 01:29.790
And we can get our props mostly from the text field props and the use controller props.

01:29.790 --> 01:34.380
But inside here I'll specify a label and give it a type of string.

01:34.410 --> 01:36.810
And then below or after the curly bracket.

01:36.810 --> 01:43.680
Here I can use ampersand, and then we can use the use controller props we get from react hook form,

01:44.730 --> 01:51.120
and we can use the text field props we get from Mui material.

01:52.380 --> 01:57.300
So when we want to use our app text input, we get all of the props that we typically have with a text

01:57.300 --> 02:00.090
field and then we can pass in.

02:00.420 --> 02:03.750
And I won't destructure anything from this because it will be too big.

02:03.750 --> 02:06.150
I'll just use props and props.

02:06.540 --> 02:15.060
And then for our use controller we can, in curly brackets use the spread operator and pass in the props.

02:15.090 --> 02:18.270
And that's the argument that our use controller needs.

02:18.270 --> 02:24.660
And then we can destructure from use controller we can get hold of the field states and the field,

02:24.870 --> 02:27.510
and then we can return inside.

02:27.510 --> 02:38.280
Here we can use a text field, make it self-closing, and we can use the spread operator again to pass

02:38.280 --> 02:39.870
in all of the props.

02:41.070 --> 02:46.620
And then we can use curly brackets, spread operator again and use all of the field props inside here

02:47.010 --> 02:53.220
the multi-line property will get from props dot multi-line.

02:53.220 --> 02:58.290
And like I say, we've got all of the text field properties available inside here too.

02:58.830 --> 03:00.780
We'll do the same for Rose, just in case.

03:00.780 --> 03:06.510
We want to use this as a text area and specify props and rows.

03:07.560 --> 03:14.280
And also we'll specify the type in here so that we can use it as a text input or a number input or one

03:14.280 --> 03:16.140
of the other types of inputs of course.

03:16.140 --> 03:19.350
So I'll specify props dot type for this.

03:21.690 --> 03:23.730
We'll make it full width.

03:24.660 --> 03:28.080
We'll give it a variant of outlines.

03:30.060 --> 03:33.360
And we can also specify our error properties here as well.

03:33.360 --> 03:37.860
So I'll specify error equals and then in curly brackets double exclamation mark.

03:37.860 --> 03:41.250
And then we'll check the failed states and see if it has an error.

03:41.250 --> 03:49.680
And then we can also use the helper text and set this equal to failed states dot error dot message.

03:51.450 --> 03:53.550
So that's our reusable text input.

03:53.550 --> 03:54.810
Pretty straightforward.

03:54.810 --> 03:57.910
But It is straightforward.

03:57.910 --> 04:01.810
And if we were not using TypeScript, that would be the end of our job here.

04:01.810 --> 04:07.600
But let's see how we get on inside our product form when we try and make use of this.

04:07.630 --> 04:15.610
So instead of the controller, etc. going on here, we can use our app text inputs we've just created.

04:15.640 --> 04:17.410
I'll give it a self-closing tag.

04:17.410 --> 04:18.370
We need to pass this.

04:18.370 --> 04:23.650
The control that we've brought in from our react hook form up here.

04:23.680 --> 04:29.020
So we pass each input the control and we need to give it a name.

04:29.020 --> 04:31.870
And this is going to be name of name.

04:31.900 --> 04:36.100
And I'll give it a label equal to the product name.

04:36.700 --> 04:39.670
And we've got a warning here.

04:39.670 --> 04:44.320
And if we hover over this then this is going to look pretty nasty.

04:44.890 --> 04:52.540
And the reason is that it's expecting a control with the type of field values.

04:52.810 --> 04:57.440
But our control that we're Her passing has a type of control.

04:57.440 --> 04:59.660
And then this is our product schema.

04:59.690 --> 05:01.940
Effectively our create product schema.

05:01.970 --> 05:04.970
So it's not matching what the controller is expecting.

05:04.970 --> 05:10.880
So we could cheat and we could say well this is going to get complicated very quickly.

05:10.880 --> 05:14.330
And we could just remove our product schema from here as the type.

05:14.330 --> 05:17.600
And then our control would be happy.

05:17.600 --> 05:22.790
But then we start playing whack a mole with other elements in our page, because now our onsubmit is

05:22.790 --> 05:23.300
not happy.

05:23.300 --> 05:26.780
So we'd have to change that to something else as well.

05:26.780 --> 05:33.920
And we could just use field values and take away the type benefits we do get with Zod and the schema

05:33.920 --> 05:36.380
that we created and that works.

05:36.380 --> 05:41.660
And that would work for our input here, but it does feel a little bit like cheating.

05:41.660 --> 05:46.400
But let's just make sure that this is working as we stand at the moment, and then we can come back

05:46.400 --> 05:47.690
and fiddle with the types.

05:47.690 --> 05:50.210
So let's go back to our application.

05:50.210 --> 05:54.710
I'll just refresh this because we're going to get some console warnings as we've been changing the code.

05:54.740 --> 06:00.110
I'll click on create and we can see we've got our text input provided with the product name.

06:00.290 --> 06:05.630
If I click in, in fact, we don't have validation at the moment because I've disabled that temporarily.

06:05.630 --> 06:08.150
But we should be able to start typing in here.

06:08.150 --> 06:09.710
And I've got an issue here.

06:10.430 --> 06:14.510
Once again, it's going to be that uncontrolled input to be controlled.

06:14.540 --> 06:20.090
So we need to give our text field or our controlled input effectively a default value as well.

06:20.120 --> 06:22.310
So let's go back to the app text input.

06:22.460 --> 06:25.970
And just after the props we'll add a default value.

06:25.970 --> 06:32.660
And we'll set it to be just an empty string which should remove that warning we get in the console.

06:32.960 --> 06:36.440
And I'll click on create again type in test.

06:36.440 --> 06:40.880
Click submit and we get our output into the console there.

06:41.810 --> 06:43.220
So the input is working.

06:43.220 --> 06:51.410
But do we want to use the cheats approach or do we want to provide our schema type that we created.

06:51.440 --> 06:57.030
I'm going to say that we're not going to cheat, but this is slightly tricky to accomplish.

06:57.120 --> 07:04.890
So I'll put things back to how they were with the create product schema, and where we've got the control

07:04.890 --> 07:06.630
that now has the warning.

07:06.630 --> 07:12.300
And to resolve this warning, that does involve some trickier aspects of TypeScript that we'll need

07:12.330 --> 07:13.110
to take a look at.

07:13.110 --> 07:16.560
So let's head over to our app text inputs.

07:16.800 --> 07:19.290
Now we need to get field values to this.

07:19.290 --> 07:24.480
We can't use our create product schema because we would like to use this input in other locations as

07:24.480 --> 07:25.110
well.

07:25.110 --> 07:30.360
And we need to give this some type information so that we can use our control in this way.

07:30.360 --> 07:34.260
So we need to use generic types which means giving it a type.

07:34.260 --> 07:42.480
In this case for our props, I'm going to specify T and say that this extends the field values.

07:42.570 --> 07:45.480
That's what we used in our form just now.

07:45.480 --> 07:49.530
And we know field values works with our control.

07:49.590 --> 07:56.850
Now what we also know if we go back to our product form and we hover over the control, then each one

07:56.850 --> 08:02.700
of our inputs is going to have a property unique to that particular control.

08:02.700 --> 08:07.050
So we also need to get that information into our type info as well.

08:07.050 --> 08:13.800
And we can do that by specifying the name property in here and saying it has a key of T.

08:13.920 --> 08:21.120
And that will give us type safety for the name of the inputs that we're using with our text input,

08:21.660 --> 08:27.390
based on the schema that we created for the create product schema.

08:27.900 --> 08:31.980
So back in our text input bit, more work to do with our types.

08:32.010 --> 08:36.240
Our use controller props will give this the type of T as well.

08:38.070 --> 08:45.180
And when we use a generic type in this way, then at compile time this gets replaced with what we're

08:45.210 --> 08:48.870
actually using when we use this text input in our product form.

08:48.870 --> 08:56.520
So it's going to know that for our text input, we're using a type of create product schema that extends

08:56.520 --> 08:58.560
the field values.

08:58.560 --> 09:01.110
So we've got our use controller props of type T.

09:01.830 --> 09:05.820
Then we need to give our app text inputs a type property as well.

09:05.820 --> 09:07.050
And we'll specify t.

09:07.320 --> 09:11.580
And once again we'll say extends field values.

09:11.970 --> 09:17.010
And then we can give our props the type of T as well.

09:17.760 --> 09:21.060
So as with anything in TypeScript we fix one thing.

09:21.660 --> 09:25.680
Because now if we go back to our product form we've fixed the control.

09:25.710 --> 09:26.310
Yay!

09:26.310 --> 09:27.810
But we've broken our text input.

09:27.810 --> 09:31.170
So whack a mole so we can't use default value here.

09:31.170 --> 09:36.960
We'll take that out and instead we'll specify the value inside the text field itself.

09:36.960 --> 09:43.020
Now control inputs instead of using default value we use value inside here.

09:43.020 --> 09:46.860
But we have to define the value which is going to come from the fields dot value.

09:46.860 --> 09:49.690
Or it's just going to be an empty string.

09:49.720 --> 09:52.360
And now let's go back and clean up our product form.

09:52.360 --> 09:56.080
There's way too many errors here, but we've got things that we're not using that we've imported.

09:56.080 --> 09:57.700
I've got something commented out here.

09:57.700 --> 10:00.100
Let's uncomment that.

10:00.100 --> 10:06.670
And I'm going to remove the mode of untouched because that's giving us an issue with testing our validation

10:06.670 --> 10:08.590
because we've only got one input field.

10:08.590 --> 10:14.440
And I'll also remove the unused imports from in here as well at the same time.

10:14.470 --> 10:16.750
And great, now everything is clean.

10:16.750 --> 10:19.810
But does it work as we'd expect it to?

10:19.840 --> 10:27.940
So if we go and take a look and let's just refresh this page and I'll click create.

10:27.940 --> 10:32.890
And if I type in a product name I'll say test and click submit.

10:32.890 --> 10:35.710
I'm not going to be able to submit because of the validation.

10:35.710 --> 10:40.270
But if I do take out the product name and then I click submit.

10:40.270 --> 10:43.720
Still nothing that caught me by surprise.

10:43.720 --> 10:47.800
Let's go back to our product form and see what's going on here.

10:47.830 --> 10:48.130
Okay.

10:48.170 --> 10:50.600
let's take out the validation temporarily.

10:50.630 --> 10:54.650
Make sure that we can submit without validation being involved.

10:54.650 --> 10:58.970
So I'll just refresh this page again and I'll click create.

10:58.970 --> 11:01.670
And just type in test and click submit.

11:01.670 --> 11:04.040
And we see the output inside here.

11:04.040 --> 11:08.090
But I was hoping to see validation errors as well.

11:08.210 --> 11:12.140
And let's put the schema back in again.

11:12.170 --> 11:13.850
The Zod resolver back in.

11:14.390 --> 11:20.060
If we don't use the mode of on touch, then in theory what should happen when I click submit is I should

11:20.090 --> 11:23.420
at least see the validation error for the single inputs that we have here.

11:23.420 --> 11:28.610
So I'm just going to refresh that page again and I'll click create and I'll submit.

11:28.610 --> 11:29.420
And there we go.

11:29.420 --> 11:30.860
We do see the validation.

11:30.860 --> 11:34.010
And if I start typing the validation error should go away.

11:34.040 --> 11:36.140
Obviously with just a single input.

11:36.140 --> 11:41.570
This is hard to demonstrate our validation working when we've created all of the validation in our schema.

11:41.570 --> 11:44.270
So we need more inputs effectively.

11:44.300 --> 11:47.900
And in the next lesson we'll start to look at addressing just that.
