In this short tutorial, we will see how to validate form data using Laravel Inertia and Vue 3. For this section, we will use Vue 3 SFCs method <script setup>
.
1. Create a simple CategoryController.php
and validate and store data.
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'slug' => 'required|string|max:255',
]);
Category::create([
'name' => $request->name,
'slug' => \Str::slug($request->slug)
]);
sleep(1);
return redirect()->route('category.index')->with('message', 'Category Created Successfully');
}
2. Create CategoryStoreRequest.php
to define validation rules.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CategoryStoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'name' => 'required|string|max:255',
'slug' => 'required|string|max:255',
];
}
}
CategoryController.php
public function store(CategoryStoreRequest $request)
{
Category::create($request->validated());
sleep(1);
return redirect()->route('category.index')->with('message', 'Category Created Successfully');
}
Laravel Inertia Form helper
Laravel inertia form come with form validation. So you can easily validate form.
<template>
<form @submit.prevent="form.post('/login')">
<!-- email -->
<input type="text" v-model="form.email">
<div v-if="form.errors.email">{{ form.errors.email }}</div>
<!-- password -->
<input type="password" v-model="form.password">
<div v-if="form.errors.password">{{ form.errors.password }}</div>
<!-- remember me -->
<input type="checkbox" v-model="form.remember"> Remember Me
<!-- submit -->
<button type="submit" :disabled="form.processing">Login</button>
</form>
</template>
<script>
import { useForm } from '@inertiajs/inertia-vue3'
export default {
setup () {
const form = useForm({
email: null,
password: null,
remember: false,
})
return { form }
},
}
</script>
Category/Create.vue
<script setup>
import BreezeAuthenticatedLayout from "@/Layouts/Authenticated.vue";
import { Head } from "@inertiajs/inertia-vue3";
import BreezeButton from "@/Components/Button.vue";
import { Link } from "@inertiajs/inertia-vue3";
import { useForm } from '@inertiajs/inertia-vue3'
const form = useForm({
name: '',
slug: '',
});
const submit = () => {
form.post(route('category.store'));
};
</script>
<template>
<Head title="Category Create" />
<BreezeAuthenticatedLayout>
<template #header>
<h2 class="text-xl font-semibold leading-tight text-gray-800">
Category
</h2>
</template>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<!-- <form @submit.prevent="submit"> -->
<form @submit.prevent="form.post(route('category.store'))">
<div class="mb-6">
<label
for="Name"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>Name</label
>
<input
type="text"
v-model="form.name"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder=""
/>
<div v-if="form.errors.name" class="text-sm text-red-600">{{ form.errors.name }}</div>
</div>
<div class="mb-6">
<label
for="slug"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>Slug</label
>
<input
type="text"
v-model="form.slug"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
/>
<div v-if="form.errors.slug" class="text-sm text-red-600">{{ form.errors.slug }}</div>
</div>
<button
type="submit"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
:disabled="form.processing"
:class="{ 'opacity-25': form.processing }"
>
Submit
</button>
</form>
</div>
</div>
</div>
</div>
</BreezeAuthenticatedLayout>
</template>