00:08
our application. So let's extract this logic out into a reusable composable so that we don't have to replicate it inside of each one of our components.
00:16
So within our inertia directory, let's create a brand new file inside of here and we'll put it inside of a folder called composables.
00:22
Our file itself is going to be called a resource actions and we'll make that a .ts file.
00:28
Our underlying goal with this composable is to extract out that reusable dialog based information, which is the open and closed state and its form used inside of the dialog itself.
00:38
Once we get around to deleting, we can also add the delete confirmation and actual deletion steps inside of here as well.
00:44
For now, let's get started by exporting a function called use resource actions, and
00:50
this is going to take in a generic type and we'll give that generic type a name of resource.
00:56
This will be the resource that we're either creating, updating, or eventually deleting with this use resource actions.
01:04
For our project, that could be organizations, lessons, modules, access levels, difficulties, and the like. We're always going to want to provide our resource type in as a generic to this use
01:13
resource action composable. However, the form data itself, we're going to want to be able to derive that from the
01:20
object passed in as its default state, as that's what inertia does to grab the actual type for the form. In order to do that with our composable, we're going to need to use currying, and that's
01:30
really just a function that returns back another function. For this, we'll return another function, and we're going to give this curried function
01:37
a generic as well called form, and this form is going to extend object.
01:44
This is going to be the type of the default state we're passing into the use form composable, so we'll call our parameter here default form and give it the type of form from that generic.
01:54
We'll go ahead and instantiate an instance of the form using the use form composable
01:59
from inertia, passing in that default form data as its argument. We can go ahead and start our return back now and ensure that we're returning back that
02:09
form so that we have access to it where we're calling this composable. Now in addition to our form, we're also going to want a dialogue object as well.
02:17
This is going to house the open and close state of our create and update dialogue, and we'll want that to be a ref from view, and this will have is open defaulted to false.
02:26
The resource object will start as undefined, and it's also going to have an open method inside of it that takes in the optional resource.
02:35
Now the type of that resource is going to be the resource that we're passing into the parent function from our use resource actions generic.
02:43
In addition to that, we also want to accept an updated data for our form's default state,
02:49
and we're going to default this to an empty object and set its type as the form being derived from the default form that we're passing in.
02:58
In terms of our resource, we also want to make sure that the resource object that we're accepting in here is the non-ref unwrapped type.
03:04
So we're also going to use views unwrap ref to ensure that the type for this isn't wrapped in views reference.
03:11
We can hit command dot and update our import for view to include that there as well. So when we call open for our dialogue, what we're going to want to do is update the defaults
03:21
of our form with any data that we may pass into the data parameter of the open method. So for that, we can do form, and then we can update the defaults by calling defaults, and
03:31
this accepts an object of the new default values. So we can first spread in the default form initially passed into this composable via
03:40
currying right here. Then we'll spread in the updated data so that it gets applied over any of the default form properties that also exist.
03:49
Then we'll go ahead and call reset on our form so that those defaults get applied to the actual state of the form.
03:56
These two lines are very important for being able to edit data whenever we get around to that. We'll be able to pass in the edit data via the second parameter of our open.
04:05
We update the form with those default values, and then we reset the form to make them apply to the actual values of the form.
04:13
This is an alternative to going through our form line by line and updating each one of those properties directly from our data.
04:20
So we could do this line by line, or we could have it automatically happen for each one of the properties that we pass in via form defaults and form reset.
04:29
Next we need to update our resource and is open flags of our dialogue. So we can do dialogue.value, since it's a ref, .resource equals the resource that we've
04:39
passed in. This is going to be useful if we need to display any information about the resource directly inside of the dialogue. Now we're going to get a red squiggly, and that's just because this resource doesn't really have a type at present.
04:48
It's just undefined. So we need to apply a type to our ref in order to fix that. Then lastly, let's go ahead and just open up our dialogue by setting is open to true. Okay.
04:58
Now as for setting a type for our dialogue ref here, we're going to need access to the resource type as well as the form type.
05:06
So we're going to define these interfaces inside of our curried function. So we can do interface dialogue, and we'll have our is open, set that to a type of Boolean.
05:16
We'll have our optional resource set to the type of our resource being passed in. And then we'll have our open method that accepts in that optional resource.
05:25
And again, we need to specify that this is the unwrapped type of that resource and then the optional data of type form. And then these methods don't return anything.
05:34
So we'll set the return type there to void. For our ref, we just want to apply the type as our dialogue.
05:41
And now everything is happy, except that once a dangling comma, so we can add that in too. Then we also want to provide access to that dialogue outside of this composable. So we'll return that as well.
05:51
And then we have access to both our dialogue and our form. Before we close this out, let's go ahead and also define an additional function just called on success.
06:00
This will be the post put delete on success handler. That's just going to set the dialogue value for is open to false to close the dialogue.
06:10
And then it's also going to clear out the resource loaded into the dialogue as well. So we just set that there to undefined. We'll return back that on success function as well.
06:20
And we should be all set now. Let's jump back into our organization select and refactor everything to make use of this composable. So just underneath our organization ID, let's do const.
06:30
We can extract out that form, the dialogue and the on success function from our use resource actions composable.
06:39
Now we need to provide the generic type of our resource for our organization select. That's going to be the organization DTO type.
06:47
And then our use resource action returns a function. So we need to also call that function and provide in our default form state, which is
06:55
just our name set to an empty string. So now we'll use form in place of dialogue form, and we'll use dialogue.isOpen in place of our isDialogueOpen.
07:05
So we can get rid of both of these ref and use forms, which will give us red squigglies indicating where we need to make these refactors.
07:13
So here we want to replace dialogue form with just form. And then for these two, these are taking place inside of our on success function, and it's just closing out and resetting our form.
07:22
Well, with our resource action, the form resets on open, so we don't need to worry about resetting. But we do want to close out the dialogue, and we also want to clear out the resource set via the dialogue whenever we open.
07:32
So we can replace this on success with the on success function from our use resource actions, which simplifies it quite a bit.
07:39
If we continue our scrolling, here is where we're opening up our dialogue, and this is for adding in a new organization. So for this, we want to call dialogue open.
07:49
And since this is meant for create, we don't want to pass in a resource nor any form data. Instead just leave those empty.
07:57
And then we move on to our form dialogue, where the is dialogue open now replaces with our dialogue.is open.
08:04
And then dialogue form.processing is just form.processing. And then we also have our form name and form errors. With that, everything should be good to go.
08:14
Just now using our use resource actions composable. So let's open our browser back up. Let's try creating a new organization one more time.
08:21
So add new organization and let's call this testing use resource actions and hit add organization.
08:29
And voila, everything worked the exact same as we had it prior to this change. Just now we have a very reusable form state for doing this, and we'll be able to make
08:37
use of this for almost every resource that we have inside of our application.