Laravel and Vue.js: How to Display Validation Errors

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.

Invalid Form


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.

Success Message

No comments or questions yet...

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 52 courses (943 lessons, total 46 h 42 min)
  • 75 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials