news Apr 18, 2026 · 65 views · 3 min read

Mastering Forms in Laravel + Inertia + Vue 3

Learn how to streamline form handling in Laravel + Inertia + Vue 3. From setup to file uploads and validation, this guide covers efficient form management using Inertia's useForm().

Mastering Forms in Laravel + Inertia + Vue 3

Mastering Forms in Laravel + Inertia + Vue 3

Creating forms in a Vue single-page application that communicates with a Laravel backend can quickly become complex. Traditional methods often involve manual error mapping, axios calls, and state management. However, Inertia's useForm() simplifies these processes significantly, allowing for more efficient form handling.

Quick Setup

To begin, set up a Laravel project with Inertia and Vue 3 pre-configured:

laravel new my-app --using=laravel/vue-starter-kit
cd my-app
npm install

Run the servers:

php artisan serve  # Laravel on :8000
npm run dev        # Vite on :5173

Visit http://localhost:8000 to see the default authentication scaffolding in action. If you're integrating Inertia into an existing project, refer to the official guide.

Understanding useForm()

useForm() handles form data, loading states, error mapping, and resetting automatically:

import { useForm } from '@inertiajs/vue3'

const form = useForm({
    name: 'John',
    email: 'john@example.com',
    avatar: null,
})

Key functions include:

  • form.post(route('profile.update'))
  • form.reset()
  • form.clearErrors()

These methods streamline form management without manual axios calls.

Creating and Validating Forms

First, define the Vue component:

<script setup>
import { useForm } from '@inertiajs/vue3'

const props = defineProps({
    user: Object
})

const form = useForm({
    name: props.user.name,
    email: props.user.email,
})

function submit() {
    form.post(route('profile.update'))
}
</script>

<template>
    <form @submit.prevent="submit">
        <div>
            <label>Name</label>
            <input v-model="form.name" type="text" />
            <span v-if="form.errors.name">{{ form.errors.name }}</span>
        </div>
        <div>
            <label>Email</label>
            <input v-model="form.email" type="email" />
            <span v-if="form.errors.email">{{ form.errors.email }}</span>
        </div>
        <button type="submit" :disabled="form.processing">
            {{ form.processing ? 'Saving...' : 'Save Changes' }}
        </button>
    </form>
</template>

In Laravel, create a FormRequest for validation:

public function rules(): array
{
    return [
        'name'  => ['required', 'string', 'max:255'],
        'email' => ['required', 'email', 'unique:users,email,' . auth()->id()],
    ];
}

File Uploads with Progress

To handle file uploads, update useForm():

const form = useForm({
    name: props.user.name,
    email: props.user.email,
    avatar: null,
})

For the file input:

<div>
    <label>Avatar</label>
    <input type="file" accept="image/*" @change="form.avatar = $event.target.files[0]" />
    <span v-if="form.errors.avatar">{{ form.errors.avatar }}</span>
</div>

To track upload progress:

<div v-if="form.progress">
    <progress :value="form.progress.percentage" max="100">
        {{ form.progress.percentage }}%
    </progress>
    <span>{{ form.progress.percentage }}%</span>
</div>

On the Laravel side, update validation rules for file uploads:

'avatar' => ['nullable', 'image', 'mimes:jpg,jpeg,png,webp', 'max:2048'],

Conclusion

Inertia's useForm() offers a robust mental model for form handling in Vue applications, making it the go-to solution for modern web development.

Discussion

0 Comments

Leave a Comment

Comments are moderated and will appear after approval.