Forms are an every day task for many developers. Also it’s one of the most boring ones in my opinion. Recently I decided to make a rather complicated form in a Laravel project I ran with a lot of Vue.js magic. But how we validate input in such a case ? Do I keep the normal flow of returning with input() and errors() ? Well, I would prefer not to do that.



There are many solutions out there, the most popular one is the Vee-validate component. The problem I had with those tools is that my validations where sometimes also complicated so the ready ones was not enough and I had to write a lot of custom things to do the job.

undefined


Why not force the Laravel framework to do the job? I asked my self. It’s already doing it amazingly good. It would be great to have one place and one codebase for validation, maintaining such a thing would be a bliss. After some tweaking I discovered an extremely easy way to do this and I thought it would be great to share it with the world. The Vee-validate component works this way:

  1. User submits the form.
  2. On submit event vee-validate is validating stuff, client side.
  3. If everything is ok, you make a normal post of the form with the data.
  4. If there are errors, you have an error property that you can use to show/hide errors and fields.

This flow gave me the idea of the following trick and so I basically replaced the second step.

What is the trick ?

The form tag is pointing to a vue method. I am using the “prevent” mode so the form is not actually posted anywhere.

<form method="POST" action="https://yoururl.com" accept-charset="UTF-8" id="yourForm" @submit.prevent="submitForm()">

Let’s see the submitForm() method in my vue.js instance.

/// Vue.js instance
submitForm: function(){
     // generate the data variable first, with the needed input.
axios.post('/your-url',data).then(function(response){
         document.getElementById("yourForm").submit();
   }).catch( error => {
       this.formErrors = error.response.data.errors;
   });
}

So, what is happening here? You make a post request using the axios package to the same route as the action url of the form. By using a Form Request object in this method, in case of failure Laravel responds with the errors in JSON format automatically. If there are errors, you catch them in the catch block and assign them to a variable and do what ever is needed to alert the user about the errors.

On the other side, if you post a perfect form without errors, the Laravel Controller sees that it is an Ajax request and

// Laravel controller method
public function store(YourRequestValidation $request)
{
     if ($request->expectsJson()) {
      return response()->json(['valid' => true], 200);
     }
     // Your rest controller logic that will handle the form data.
}

with this special if() block, after the successful validation we are redirected with a 200OK status so we can be inside the axios.then() block. Only thing left is to make the actual, initial form post that we prevented in the first place.

You may think that, oh my! this will trigger vue submit method and it will prevent this action, but no, that’s not the case. The actual form post will be made and Laravel this time will validate and completely skip this if block because this time conveniently it’s not an Ajax request.

So, what is accomplished here? I have only one Request object that handles the validation. I don’t have to worry about maintaining the validation code in both JS (Front) and Laravel ( Back), I have only one place to do that. I am using the perfect Laravel validation flow that I know well and last but not least, I don’t have a page refresh after the validation, so it feels snappy. The 2 Http requests for doing this is really not a problem, the gains are more important in this case.

I guess you can easily tweak this if you actually want to make an Ajax request the second time as well.

Hope you found it interesting, if you have another approach I would love to hear about it :-)

! Update !

A dear friend of mine Kyriakos ( also in the core team of laravel.gr community) prepared a skeleton with this method at https://github.com/kyrpas/vuejs-laravel-validation . Many thanks mate, I am sure it will help a lot :-)