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!