WEBVTT

00:00.000 --> 00:05.580
Okay, the next thing we're going to take a look at is adding the ability to upload a file via our browser

00:05.580 --> 00:06.090
as well.

00:06.090 --> 00:11.400
And if we take a look at our product form, then effectively we're going to have the ability to drag

00:11.400 --> 00:16.320
and drop an image inside here or click and select an image from the file system.

00:16.440 --> 00:20.790
And we're going to get some help with this in the form of react dropzone.

00:20.790 --> 00:25.830
This gives us the utility so that we can just display a drop zone on our page.

00:25.830 --> 00:30.630
And that gives you that functionality that I was referring to.

00:30.660 --> 00:33.480
So it's just a matter of installing React Dropzone.

00:33.480 --> 00:39.630
And if we take a look at a basic example then it gives us this kind of functionality.

00:39.660 --> 00:45.360
If I just go and drag a file in to this drop zone, then we can drop it in.

00:45.360 --> 00:50.820
And then we've got access to the file, which we're going to effectively add as one of our form properties

00:50.820 --> 00:51.540
effectively.

00:51.540 --> 00:52.860
But that's the idea of this.

00:52.860 --> 00:54.930
And that's what we'll add now.

00:54.930 --> 00:56.460
So we'll go across to VS code.

00:56.460 --> 00:59.190
And this is something that we're going to need to install.

00:59.220 --> 01:00.600
I'll clean things up at the top.

01:00.600 --> 01:05.570
It feels like it's getting busy up there and I'll go into the client folder.

01:05.570 --> 01:07.550
So I'm just going to CD into the client.

01:07.550 --> 01:11.870
Please make sure you're in that client folder before adding any npm installs.

01:11.870 --> 01:16.010
And I'm just going to use npm install react dropzone.

01:16.040 --> 01:21.440
Now if you're on a stable version of react 19, then you won't need to do what I'm about to do, which

01:21.440 --> 01:27.020
is add the legacy dash peer dash deps switch.

01:27.050 --> 01:30.590
I'm 99% certain that's going to be required for myself.

01:30.590 --> 01:36.200
And now Lance is installed and available, so now we can go ahead and use it.

01:36.200 --> 01:43.610
So we will just make this a shared component, just like the other ones that we've added so far for

01:43.610 --> 01:46.100
our select input and our text input.

01:46.100 --> 01:55.190
And I'm just going to right click the components folder and say app dropzone dot TSX.

01:55.490 --> 02:00.260
And once again I'm just going to use the text input just to get the starting point for this.

02:00.260 --> 02:07.430
I'm just going to control a Ctrl C and paste it inside here, because it is going to be a form input

02:07.430 --> 02:09.410
that we're working with here.

02:09.980 --> 02:14.330
We don't need a label for this one, so I'll remove that from the props.

02:14.330 --> 02:18.080
I'll keep the field values and the controller props.

02:18.080 --> 02:23.060
And we're not going to extend from anything on this one apart from the use controller props.

02:23.060 --> 02:28.160
So I'll remove the text field props, but we'll keep the use controller.

02:28.160 --> 02:33.110
And I'll just change the name of this to App Drop Zone.

02:33.590 --> 02:39.800
And this is going to extend field values and props etc. because we still need the field functionality

02:39.830 --> 02:42.290
so that we can add this as part of our form.

02:42.920 --> 02:49.010
Because if we remember what we did in postman, then we needed to send up the image as a file inside

02:49.010 --> 02:52.010
the form body or form data.

02:52.010 --> 02:54.200
That's how we're sending it up to our API.

02:54.380 --> 02:57.500
And then we don't need the text field inside here.

02:57.500 --> 02:59.240
So we can remove this.

02:59.240 --> 03:05.020
And let's go across to the docks and see if we can just copy anything from their basic example, just

03:05.020 --> 03:09.130
as a as a quick look to make sure we've got the functionality we need.

03:09.340 --> 03:14.950
So inside here inside this basic example then we use a hook for use drop zone.

03:14.950 --> 03:20.920
And then this part here is so that they can display the file path and the file size.

03:20.920 --> 03:24.220
We saw that in this example up here.

03:24.970 --> 03:29.290
And then we've got our return statement with stuff.

03:29.290 --> 03:34.840
Let's just copy the elements from here I'm going to copy the use drop zone hook.

03:34.840 --> 03:36.160
We need that anyway.

03:36.160 --> 03:39.190
So I'm just going to add that inside this component.

03:39.370 --> 03:45.130
And I'll just bring in using the quick fix the add import from react Drop zone.

03:45.310 --> 03:49.660
And then in the return statement let's take a look at this.

03:50.590 --> 03:52.720
We've got a section here.

03:52.720 --> 03:57.910
And then we're using the Get Root props and giving it a class name of drop zone.

03:57.910 --> 04:00.990
And then the input drag and drop some files.

04:01.020 --> 04:03.090
Okay, let's just copy this and see what it gives us.

04:03.090 --> 04:05.340
We'll be replacing it very, very soon.

04:05.340 --> 04:09.420
So if the documentation has changed then feel free to copy this in.

04:09.420 --> 04:10.350
But it's only temporary.

04:10.350 --> 04:15.720
Just to make sure we've got the basic functionality working, I'll put it inside a fragment and I'll

04:15.720 --> 04:16.920
just paste in.

04:17.490 --> 04:19.980
In fact, I didn't need the fragment there for some reason.

04:19.980 --> 04:21.300
I thought that was two different elements.

04:21.300 --> 04:25.260
So I'll just paste in the section that we have and great.

04:25.290 --> 04:26.070
Okay.

04:27.300 --> 04:29.070
So I'm going to take out this aside.

04:29.070 --> 04:30.960
I'm not even going to use that.

04:30.960 --> 04:34.470
But we do need something to use for the accepted files here.

04:34.470 --> 04:38.790
This is what we store the file that's dropped in into our browser.

04:38.790 --> 04:42.990
So just above the return statement I'm going to create an on drop function.

04:42.990 --> 04:48.930
And for this one we're going to use another hook that we haven't looked at yet.

04:48.930 --> 04:52.440
It's the equivalent of usememo but for functions.

04:52.440 --> 04:55.650
And this is called use callback.

04:55.650 --> 04:58.560
So I'm going to use this particular hook.

04:58.560 --> 05:02.520
And we're going to pass in as a parameter a callback function.

05:02.520 --> 05:09.030
So we'll pass in accepted files, add the arrow and then open curly brackets.

05:09.030 --> 05:14.040
And I'm just going to, for the time being console log the accepted files.

05:14.610 --> 05:17.340
And then in the dependencies for the use callback.

05:17.370 --> 05:20.670
This operates just like a Usememo or a Useeffect.

05:20.670 --> 05:26.760
We need to give this a dependency array, and the idea is that this function, this Ondrop function

05:26.760 --> 05:27.780
is Memoized.

05:27.780 --> 05:33.840
So if our component gets rerendered, then the function doesn't get recreated.

05:33.840 --> 05:37.080
And I don't need any dependencies inside here.

05:37.080 --> 05:44.370
And I'm getting a warning about accepted files having a implicit any type.

05:44.400 --> 05:51.030
Okay, so I'll ignore the TypeScript warnings for now, but I'll give it an explicit any type for the

05:51.030 --> 05:57.390
time being, although I'm sure we can get away with just using an actual type of file here.

05:57.390 --> 06:01.020
And yeah, sure, that's a bit more like it, so I won't use the any type.

06:01.020 --> 06:06.750
I'll use file array because we can drop multiple files into our react dropzone.

06:06.960 --> 06:11.160
And then we need to use our on drop function.

06:11.160 --> 06:13.560
But that needs to be passed to the use dropzone.

06:13.560 --> 06:18.240
So I'm just going to cut this and move it below the on drop function.

06:18.240 --> 06:24.510
Because we're going to pass that in as an option in curly brackets.

06:24.510 --> 06:32.670
We're going to use our on drop function, which is named exactly the same as the property that dropzone

06:32.670 --> 06:33.360
is looking for.

06:33.360 --> 06:36.270
So we don't need to say on drop colon on drop.

06:36.270 --> 06:37.980
We can just shorthand that.

06:37.980 --> 06:41.670
And we don't need the accepted files from here either.

06:41.670 --> 06:46.770
So I can remove that and let's see how we're getting on.

06:46.770 --> 06:48.870
This should give us enough to get started with.

06:48.870 --> 06:51.690
So I'll remove the unused import there.

06:52.170 --> 06:54.180
We've got our use controller props.

06:54.180 --> 06:56.160
We're not hooking this up to our form just yet.

06:56.190 --> 06:57.390
We will do soon.

06:57.390 --> 06:59.340
So I'll ignore those warnings as well.

06:59.340 --> 07:10.790
And let's head over to our product form, and we will replace our app text inputs with the app dropzone.

07:11.930 --> 07:13.880
And we'll take a look.

07:14.360 --> 07:16.580
And I'm missing some required properties here.

07:16.580 --> 07:19.040
This needs the name property.

07:19.040 --> 07:20.420
So I'm going to give it the name.

07:20.420 --> 07:28.910
And I'm going to set it equal to file because that's what our create product DTO is expecting.

07:28.940 --> 07:32.810
And do I have any warnings inside the product form itself?

07:32.810 --> 07:33.290
I do not.

07:33.290 --> 07:35.330
So just the warnings in the app dropzone.

07:35.330 --> 07:39.590
But I know what they are and there's nothing else inside here causing a problem.

07:39.590 --> 07:44.030
So we should be able to go and have a quick look and see our progress here.

07:44.030 --> 07:50.690
And if I go to the create then I've got a problem reading control of course, because we also need to

07:50.720 --> 07:55.550
pass the control to the app dropzone as well.

07:55.550 --> 08:00.970
Even though we're not using the form functionality yet, we do need to pass the control and I'll set

08:00.970 --> 08:02.770
that to control.

08:03.370 --> 08:03.910
Okay.

08:03.910 --> 08:05.620
So let's give that another go.

08:05.620 --> 08:07.690
And I'll click on the create button.

08:07.690 --> 08:09.910
And now we've got our drop zone.

08:09.940 --> 08:11.650
It's not styled very well at the moment.

08:11.680 --> 08:13.030
And we will fix that soon.

08:13.030 --> 08:14.260
But I'm going to take a file.

08:14.260 --> 08:21.400
In fact let's open up the console first of all and what we would expect to see of course inside here

08:21.400 --> 08:28.060
is after we have dropped a file in, we would expect to see that file present in our Chrome DevTools.

08:28.060 --> 08:31.780
So let's just drag an image across here.

08:31.780 --> 08:37.390
We're not going to see any user interface niceness yet, but I'm just going to drop it onto the text.

08:37.390 --> 08:40.960
And then we can see that we have the file available inside here.

08:40.960 --> 08:43.810
And we've got all of the file details.

08:43.810 --> 08:45.610
That's what we're looking for right now.

08:45.610 --> 08:50.080
Let's just adjust the styling so it looks a bit more presentable.

08:50.350 --> 08:54.790
And I'll head back to the app drop zone and we can get another property from use.

08:54.790 --> 08:57.760
Drop zone called is drag active.

08:57.760 --> 09:04.800
So we know if somebody's hovering over the drag inputs or the drop zone, and let's give it some styling.

09:04.800 --> 09:12.330
So I'm going to create an object for this called DS styles equals and open curly brackets.

09:12.330 --> 09:15.210
And inside here we're going to create some styles.

09:15.210 --> 09:18.750
So I'll use Display Flex I'll have a border.

09:18.750 --> 09:23.610
And this is going to be dashed 3PX.

09:23.610 --> 09:27.840
And we'll use hash e.

09:29.280 --> 09:30.900
We'll have a border color.

09:33.990 --> 09:37.170
And we'll set that also to hash e.

09:37.590 --> 09:42.090
And that needs to be in quotes hash e.

09:43.170 --> 09:49.980
We'll have a border radius and I'll make it five pixels.

09:51.480 --> 09:53.340
We'll have padding top.

09:53.340 --> 09:56.880
And I'll set that to 30 pixels.

09:59.100 --> 10:07.360
Will align items and specify center, and we'll give it a height of 200.

10:07.390 --> 10:11.230
And a width of 500.

10:13.600 --> 10:23.170
And we'll create another object and say const ds active equals.

10:23.170 --> 10:25.600
And we'll just update the border color here.

10:25.600 --> 10:28.630
So it changes when they're hovering over it with a file.

10:28.630 --> 10:30.550
And set that to green.

10:32.170 --> 10:34.480
And let's adjust what's going on in here.

10:34.480 --> 10:37.030
I don't actually want any of that code at all.

10:37.900 --> 10:47.320
And inside here we'll have a div and we'll use the in curly brackets dot dot dot get root props.

10:47.320 --> 10:51.100
This is what we get from the drop zone for its properties that it needs.

10:51.100 --> 10:53.320
Then we'll have a form control.

10:55.900 --> 10:57.820
And we'll give it some style.

10:58.800 --> 11:02.490
And we'll check to see if the drag is active.

11:02.490 --> 11:10.110
If it is, then we'll open curly brackets and say dot dot dot ds styles.

11:10.110 --> 11:15.240
And then if the drag is active we'll also apply the DS active style.

11:15.240 --> 11:17.670
So that's going to override the border color.

11:17.700 --> 11:21.150
Otherwise it's just going to be DS styles.

11:21.150 --> 11:24.240
And we'll also give this the error property as well.

11:24.240 --> 11:27.480
So let's just move the style down inside there.

11:27.720 --> 11:30.960
Move this angle bracket down and below the style.

11:30.960 --> 11:33.270
We'll just specify the error property.

11:33.450 --> 11:40.260
And we'll check the exclamation mark exclamation mark and the field state dot error.

11:40.260 --> 11:47.580
And inside here we need an input which doesn't need any types or anything because we get the input props

11:48.090 --> 11:49.440
from drop zone.

11:49.440 --> 11:54.330
So inside curly brackets we'll say dot dot dot gets input props.

11:56.010 --> 12:06.200
And then below the input we'll use upload File, which is an icon from Mui material, and give it a

12:06.200 --> 12:07.940
self-closing tag.

12:07.970 --> 12:10.070
And we'll give it the SE property.

12:10.070 --> 12:15.260
And we're going to set the font size to be 100 pixels.

12:16.220 --> 12:25.940
Below this we'll use typography, and we'll give it a variant of H4 and just say drop image here.

12:26.810 --> 12:30.050
And we'll use the form helper text again.

12:30.050 --> 12:32.300
So if there is an error we can display that.

12:32.300 --> 12:37.310
And we'll use filled states dot error dot message.

12:40.040 --> 12:43.280
And that should make it look a bit more presentable.

12:43.280 --> 12:45.020
We've still got the field not being used yet.

12:45.020 --> 12:50.870
We need to add a bit of functionality into our ondrop, but we'll just see how we're doing right now

12:50.870 --> 12:51.620
with our drop zone.

12:51.620 --> 13:00.600
So I'll go back to the browser, I'll click create and we can see that we've got our big Drop image

13:00.600 --> 13:01.440
here.

13:02.490 --> 13:09.600
I think I'd like the border to be colored more like the other borders, but I'll leave it for now and

13:09.600 --> 13:11.820
we'll come back and adjust that soon.

13:11.850 --> 13:13.980
And let's just open up the console.

13:13.980 --> 13:15.840
Just make sure we've still got the same functionality.

13:15.870 --> 13:17.250
We haven't really changed anything.

13:17.280 --> 13:18.540
In fact, I need to refresh that.

13:18.540 --> 13:21.420
Loads of warnings in there and I'll click on create.

13:21.420 --> 13:25.950
And let's just drop an image inside.

13:25.950 --> 13:27.540
Here we can see the border.

13:28.440 --> 13:31.590
In fact I've got the whole thing taken up here.

13:31.590 --> 13:36.600
So I need to adjust the grid size because the grid is 12 along here.

13:36.600 --> 13:39.660
But that's going to change once we put something on the right hand side.

13:39.660 --> 13:43.920
And we shrink this to a grid size of six, but I can drop the image in.

13:43.920 --> 13:46.830
And then we see the file again as we did before.

13:46.830 --> 13:48.690
So progress is being made.

13:48.690 --> 13:51.360
We've now got the ability to drop files in here.

13:51.390 --> 13:56.610
I'd like to see a preview on the right hand side before they do, upload or submit the form, and we'll

13:56.610 --> 13:59.160
add the functionality for this next.
