In this example, we will show how to validate Vue.js form and display error messages from Laravel. Let's say we have a simple form to collect the user's name and email for our mailing list.
For this demonstration, we used Laravel Breeze starter kit with Vue preset.
Request validation and API Controller
Create the MailingListRequest
class with validation rules for name and email.
app/Http/Requests/MailingListRequest.php
namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class MailingListRequest extends FormRequest{ public function authorize(): bool { return true; } public function rules(): array { return [ 'name' => 'required|string', 'email' => 'required|email', ]; }}
Then make API Controller. It will validate fields using MailingListRequest
and return a success message if validation passes.
app/Http/Controllers/Api/MailingListController.php
namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller;use App\Http\Requests\MailingListRequest; class MailingListController extends Controller{ public function store(MailingListRequest $request) { // process data return response()->json(['message' => 'Thank you']); }}
Define API route.
routes/api.php
use App\Http\Controllers\Api\MailingListController; Route::post('/mailing-list', [MailingListController::class, 'store']);
Now, we can make a Vue form to submit to the API endpoint. If the data presented is invalid, the response will have a 422 response status, and Axios will throw an error. We catch the error and assign error messages from the response to the errors
variable to display those messages in the form.
resources/js/Pages/Subscribe.vue
<script setup>import { reactive, ref } from 'vue'; const errors = ref({})const success = ref('') const form = reactive({ name: '', email: ''}); function submit() { axios.post('/api/mailing-list', form) .then(response => success.value = response.data.message) .catch(error => { if (error.response.status === 422) { errors.value = error.response.data.errors } })}</script> <template> <div class="bg-gray-50 min-h-screen pt-12"> <div class="max-w-md mx-auto bg-white rounded shadow-sm p-6 text-gray-900"> <span class="text-green-600" v-if="success">{{ success }}</span> <form v-else class="flex flex-col space-y-4" @submit.prevent="submit" novalidate> <div class="flex flex-col space-y-2"> <label>Name</label> <input type="text" class="rounded" v-model="form.name"> <span class="text-red-600" v-if="errors?.name">{{ errors.name[0] }}</span> </div> <div class="flex flex-col space-y-2"> <label>Email</label> <input type="email" class="rounded" v-model="form.email"> <span class="text-red-600" v-if="errors?.email">{{ errors.email[0] }}</span> </div> <button class="bg-gray-500 text-white rounded px-3 py-2"> Subscribe </button> </form> </div> </div></template>
When validation passes, a success message will be displayed instead of a form.
I'm new to Laravel and Vue never used them before, not even php. I had to validate some input that only could be validated in the backend. I was looking for some way to pass the response to the frontend without losing any data in the page. This was the easiest and quickest solution!
I would advise against this method, considering that you are using Laravel + Vue with Inertia you shouldn't even be using axios plus this doesn't handle routing at all. Use the code in the Inertia documents - https://inertiajs.com/validation what is the point of using Laravel if you are just gonna make a js implementation.
Not all projects uses Inertia and this article has nothing to do with Inertia. If you advise against something please explain why and give some more context.
There also can be cases where you don't even have control on 3rd party endpoints.
This article is about consuming API and displaying validation errors and not about Inertia and routing, however I understand what you're trying to say, but it doesn't feel like there's appropriate context.