00:02
- So in this lesson, we're gonna mutate the actual action that's provided into our form component for the applicable HTTP method that we desire
00:11
for the form to actually use on the AdonisJS server side. This is using HTTP method spoofing. The underlying form will still use a method of post, AdonisJS will just use the method spoofing
00:21
to determine what the underlying HTTP method that it should use to match against the routes is. So first, before we actually start mutating our action here, let's go ahead and determine whether or not
00:29
we will be starting a query string or appending to an existing query string. So whether or not we'll need a question mark or an ampersand and we'll call this delimiter.
00:38
So let's do @set delimiter and it should be a simple action.includes$ then we know that we already have a query string going on. So we can set our delimiter to an ampersand,
00:47
otherwise it'll be a dollar sign. So next we can go ahead and actually set our mutated action. So we can do backticks here and we can inject in the action URL,
00:56
our delimiter_method= and then the desired method for the actual HTTP method spoofing. Then we go ahead and add in our action to our form,
01:05
just like so. We're not quite done here yet, but let's go ahead and give it a test. So let's dive into our demonstration page for our form. We have our button component here, we're just gonna switch that to a type of submit. Let's first send out our patch request.
01:15
So we'll do send patch here and I'm gonna wrap this in an @form. We'll designate our method here of patch, our action. I'm gonna dive into our routes real quick
01:24
and let's give each of these a name so that we can easily use them. .as_form_post, .as_form_put, .as_form_patch
01:31
and then lastly, as_form. Okay, cool. Dive back into our demonstration page here and now we can do route form patch
01:40
and that will give us back the URL for the form patch. They all should just be /form, but this will generate that out for us. And then we need to go ahead and end our form. Cool, so let's give that a save,
01:49
dive into our browser, dive into our demonstration here, click on our form and we get CSRF field is not a function. We might have CSRF protection on, but I bet you we have not yet
01:58
registered the middleware for that. So let's go ahead and do that now. So let's go into start, go into our kernel, scroll down to our global middleware and sure enough, it's not within the global middleware. So we'll add that here.
02:07
So we'll do import @IOC, Adonis, addons and shield. Give that a save. I'm gonna go ahead and switch this back to our form component demonstration page
02:16
and we'll dive back into the browser now and give this a refresh. There we go. So in order for us to actually see our submission here, let's go ahead and dive in and inspect the console. We're gonna go ahead and send this off. We refresh the page.
02:26
Okay. I forgot that we need to persist our log. So let's try that one more time. There we go. So now we see navigated to, we see we went to localhost 3333/form
02:35
with our underscore method of patch. So our method behavior is working okay within our component. Let's go ahead and verify that it reached the correct route within our AdonisJS server
02:44
by diving back into our editor, opening up our terminal and we can see we reached method patch for both. So that is working okay there as well. One thing our form does not account for however,
02:54
is for forms that we might want to handle with client-side JavaScript. So if we were to get rid of our method, have that action on there, we can also get rid of the action and we can try to handle this with Alpine JS.
03:03
So we can do @submit and let's just alert here. Give that a save, jump back into our browser. You see that we're getting back an error. I'm gonna close my terminal so that we can see it better.
03:11
Cannot read properties that were defined, reading includes. That's because we're expecting our action to be provided. In addition to that, we're also expecting our method to be provided
03:19
and we're requiring an underlying action to be appended onto the form. So let's go ahead and fix this issue now. Let's dive back into our form component and we just need to make these all optional.
03:29
The easiest way to do that is to just wrap these sets in an if. So we can do @if action and then end our if just like so. I'm gonna go ahead and indent those. We can give this a save
03:38
and now these should only try to run if we have an action. We can also account for this within our form attributes here by wrapping this action in an if as well.
03:46
So we can do @if action and end if and there we go. So now the action attribute will only be added if we actually have an action to add into the form element.
03:55
So let's give that a save, jump back into our browser, give this a refresh and okay, that was on my list of things I did not expect. So we have actions not defined, went okay on the first one,
04:04
but on the second one, it's not happy with it. So what we can do is instead directly check for action on the props. This will definitely return back undefined if it's not defined at all.
04:13
For safety's sake, let's go ahead and define that up here as well. We give that a save. Now we can jump back into our browser, give it a refresh and now we see our form again. I'm gonna open the console up one more time just so that we can verify
04:23
that the request actually does not attempt to happen. Actually, before we do that, let's inspect it so we can take a look at our form. And you see that we have form method post @submit of alert here
04:31
and then we can dive back into our console, send this request out and you see that we just get back an alert now and nothing got logged out to the console. We can hit okay to verify that that finishes. It did actually try to send out,
04:41
but that's because we're not preventing the underlying alert. So let's go ahead and refresh our page here. Cancel that. Let's actually do a full refresh there. Okay, dive back into our code
04:50
and this wasn't a component issue. This was a usage issue. So we'll dive back into our demonstration page and on our submit, we just need to chain off of it prevent to prevent default on the form submission
04:59
so that it doesn't actually try to send out to the server. So I'm gonna give this a refresh just to verify that it actually did refresh and then we can send this off again, hit okay and then I can see nothing went out at all to the server.
05:09
Cool. So before we move onward, let's go ahead and verify that we have the other methods taken care of here. So we'll undo the changes here for our client side script submission within our demonstration page.
05:18
Get back to where we have our method and our action designations. I'm gonna copy this form. Let's do one before patch for post. For this, we should be able to leave method off altogether.
05:26
It should just default to being a post request. Before we go about adding any others, let's go ahead and stop here to make sure that our form element properly handles that. So let's dive back into our browser
05:35
and sure enough, it does not. So we have action is not defined. So if we dive into our form component here, ah, actually taking a step back here for a second, at set is a block level variable
05:45
and that's our underlying issue for why this action failed. So if we take a step back to the previous issue where we just had if action here, I'm gonna go ahead and get rid of all of the props here
05:54
so that we can take a step back to that issue and get a better understanding of it. Okay. So let's go ahead and dive back into our browser, give it a refresh. And here we're back to having our error at the if action check. Okay.
06:04
This exists because at set will define the variable at the block level. So action will exist only within the if statement. This is going to cause issues because we also have action defined outside.
06:12
To fix this, all that we need to do is re-declare action outside. So at set action, and then define it the prop value of action. Give this a save, dive back into our browser, give it a refresh,
06:22
and there we go. So now we're back to having our forms rendered out and everything working okay. So to make the flow here a little bit more clear for those taking a look back at this later on,
06:31
I'm just gonna add $props.action to this to make it clear that, okay, we're setting a local variable action, checking for its existence based off of the prop value. If it exists,
06:40
then we're overriding it with the desired method if needed. And then we're checking it again whenever we're actually setting in the attribute. Cool. So we can give that a save, jump back into our browser,
06:48
verify everything works A-okay once more. And now we have our two different forms. They both say send patch, although this one should be a post. So I'm gonna go ahead and change that real quick. Dive back into our demonstration, send post,
06:57
and we need to change the route here to form.post. Let's go ahead and inspect, check out the console. Let's send off our post request. And you can see that it navigated
07:05
to localhost3333/form. If we dive into our terminal here within our text editor, we'll see that it submitted with a method of post. So that worked A-okay.
07:14
And then we can jump back into our browser, send off our patch. We can see there it has underscore method equals patch. Dive back into our console, and we see method patch there as well.
07:24
So that seems to be working A-okay. Now with the method left off of this form declaration. So let's go ahead and give our patch another copy.
07:32
Paste this two more times for our put and our delete. So here we'll have put, there we'll have put, and we'll do put there as well. And then we'll have delete for this one. And lastly, delete there. Okay, let's give that a save,
07:41
jump back into our browser. So now we should have four, post, patch, put, and delete. We've already verified, we can send off our post, patch, and lastly, our delete. You can see down here in the console,
07:50
our navigations match that exactly. So we have our form, which is our post. Then we have our patch, put, and our delete. If we check out our console log,
07:58
here we also have post, patch, put, and delete. So those are matching A-okay. We have our base form set up and ready to go.