00:02
is its useFormComposable helper. Now, currently we're not making use of it, we're just using views ref and then Inertia's router to send out our request. So let's refactor this to actually use
00:11
the useFormComposable rather than a ref and a router. So first from the InertiaJS view three, we want to import the useFormComposable. And this composable, just like our ref,
00:20
is going to accept in the default state of our form. So we can simply swap our ref with the useFormComposable. And then we can use the useFormComposable
00:28
to simply swap our ref with that useFormComposable. And we're no longer making use of ref, so we can get rid of that import. And voila, now our form state is now making use of the useFormComposable.
00:38
Now, you will notice that we do have a red squiggly now on our router post where we're passing in our form data. And that's because form is now doing a lot more than just maintaining our form field state. It's now our form state as a whole.
00:48
For example, if we take a look at form. You'll see that we have the ability to cancel the request, clear errors, so it maintains and holds our error data as well. Our main data defaults.
00:57
And then we have the actual keys of our form. We can get a specific key value, whether or not it has errors, whether or not the form's dirty. And then we have post, put, patch, and delete methods
01:07
that we can call to actually submit our form data to an endpoint as well. And if you need to change data at all prior to actually submitting it, there's a transform method that passes in the data,
01:17
and then you can mutate it and then return back those mutations. So for right now, let's just take a look at a simple example of this in practice. So we already have our form state being done,
01:27
and we can leave our actual view models as is, as we have the properties directly accessible off of the form as well. So our view models here are all A-okay.
01:36
Really the only thing that we need to change is switch from using our router to now using our form to send this post request out. And since we're using our form directly
01:45
that already has and knows about our form state, we can get rid of our form second argument there and just specify the endpoint that we want to post to instead. And this will result in the same behavior
01:55
that we had with our ref and our router. And of course, we're no longer making use of that router, so we can get rid of that import as well. Let's go ahead and jump back into our browser, give it a refresh there so that everything reloads.
02:05
If we try submitting with empty data, you'll see all of our errors still come back same as they did before. We'll see how we can switch those up to actually go off of our form here momentarily.
02:13
And if we start adding form data to this and send that out, and if we take a look at the post request specifically, you'll see that it has our full name provided as we filled it out on our form field.
02:23
So everything's working the same as it was before. Let's now switch up our errors to rather than going off of our errors prop, using our form. So our form maintains our error state as well,
02:33
just via form errors and then the key of the field name. So for our full name, that's gonna be form.errors.fullname to fully access the errors for that specific field. And we can do the same thing
02:43
for actually displaying it as well. And you'll notice that we get a red squiggly here where we have our join. That's because the use form helper, its default type is just going to expect this key
02:53
to have a string rather than an array of strings. So let's go ahead and see what that looks like if we just get rid of our join here. So let's get rid of that. We'll leave everything else as is. We've just changed our full name here at present.
03:03
Jump back into our browser. Let's get rid of our full name so that we actually get an error whenever we submit this and submit the form. You'll see that we do indeed actually get an array back
03:12
and it's displayed as such. What you can do is jump into your config inertia file where we're passing in our errors for our shared data.
03:20
You can mutate this and any data that we get back from it to instead just return back the first error or a join list of errors. So we can get our errors back and then we can return,
03:30
reach for the object keys of our errors and then reduce over those. We'll have our overall error object and then the key of an individual error
03:39
as the second parameter here to our reduce callback. We'll want to return an object back, merging in that object and then add to it our key with our errors key
03:49
and then join in our comma delimited list of any errors that we may have. Then we need to set our default data or our reducer. And I believe all of our Red Squiggles at this point are just formatting.
03:59
So let's give it a save. And there we go. Jump back into our register now. Since we are no longer passing through an array for our previous errors coming directly from our props, but we're rather joining those together
04:09
inside of our shared data now, we don't need to join them on our client side. So we can go ahead and get rid of these joins here as they'll simply just be a string. We'll just move that join over into our shared data
04:19
globally for inertia. Give that a save. We'll leave just our full name reaching for our form errors and we'll still read the other two from our errors prop. For right now, let's jump back into our browser
04:29
and let's try sending off this form with empty data inside of it. And you'll see that we get back all three of our errors here. The exact same as we were before that change. Just now we don't have that type error
04:39
whenever we reach for our use form errors. So awesome. Let's go ahead and switch our other two fields to now read from our form or its errors, just the same as we are with our full name. So we just really need to prefix our errors
04:49
with form there for both. So we've gotten our email and now let's do our password just like so. And now we're no longer using our errors prop. So we can go ahead and jump up to our defined props
04:59
and we can get rid of that for right now. Awesome. So we've now used the use form helper to simplify our form. We have some repetition going on here for each of our fields and we can simplify that further
05:08
by extracting it out into a form input component, which we'll do in a little bit. But first let's give this a save, jump back into our browser and let's make sure that everything's working
05:16
and finish going over the use form capabilities. So let's try sending this out once more. Let's fill out one of our fields. Can't spell my own name right there, but okay. And that seems to be working. Okay, awesome.
05:26
Hide that back away. Now, one really nice thing about the use form helper is that it actually has a processing flag on it. That's truthy whenever the form is in the middle of processing.
05:35
So for this, let's install a loader icon that we can use to add onto our button whenever our form is processing. So let's jump back into our terminal here. Let's get a new tab opened up again
05:44
and let's do npm i to install lucide-view-next. This is just an icon library. If you'll remember, we visited lucide.dev to grab our header icon.
05:54
So we'll be making use of that throughout this series for our icon sets. Cool. We have that installed. We can clear that out and close this back down. Jump up to the top of our file here
06:03
and let's import. They have a loader icon from lucide-view-next. Let's scroll back down to our button now, put these on separate lines,
06:12
make use of our loader icon, and only show it. So we'll do v-if form.inprocessing as the flag. It will be truthy if our form is in the middle
06:21
of submitting and falsy otherwise. Then we'll do class margin-right two, age four, width four, and animate spin to just make it do a spinny animation.
06:31
If we wanted to, we could also disable our form button by adding disabled and use that same form processing flag. So let's give that a save now. Jump back into our browser and let's try submitting.
06:41
So you'll see that very briefly. We had that little spinner icon show up. We click it again. You'll see it briefly show up there. So as our post request goes out and our client is awaiting result back from it,
06:51
that loader icon is showing. And then as soon as it resolves and we get our new data back, it goes away because our form is no longer processing. Awesome. Now, it's pretty typical that as you fill out a form,
07:01
so type my name out there and then we register. After you've submitted that form, you want to clear all your fields back out to reset the state. That's a pretty typical use case. So let's see how we can do that.
07:10
Where we are posting our form, the second argument here is options. And on the options, we have a relatively similar option set to what we saw
07:19
when we were taking a look at the router options, meaning that we have an on success callback that we can make use of and hook into. And we can reach for our form. And there is a reset method that we can use
07:29
to directly reset our form state back to its initial values. So the default values that we were passing into the use form hook, all of our form fields will get reset back to that value
07:39
when we call the reset. And then there is dirty flag processing and all of that will get reset too. So let's give that a save, jump back into our browser. Let's give that a refresh there and let's fill out all of our fields
07:49
so that it successfully submits. Fill out email, and then I have no clue what that password is, but there we go. You'll see that we hit register and all of our fields cleared out
07:58
whenever that's successfully completed.