Here’s a complete, step-by-step guide on how to create a modal form to submit feedback in a Laravel 12 application using Inertia.js and Vue.js.
This includes:
- Creating a feedback model and controller in Laravel
- Building a modal-based feedback form using Vue 3
- Submitting data via Inertia
- Showing success messages
📝 Overview
You’ll learn how to:
- Set up a feedback table using migrations
- Display a modal form using Vue.js
- Submit the form with Inertia’s
useForm - Store feedback in the database with Laravel
✅ Step 1: Create the Feedback Model and Migration
Run this command:
php artisan make:model Feedback -m
Edit the migration file in database/migrations/xxxx_create_feedback_table.php:
public function up(): void
{
Schema::create('feedback', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email');
$table->text('message');
$table->timestamps();
});
}
Then run:
php artisan migrate
Update your Feedback model to allow mass assignment:
// app/Models/Feedback.php
protected $fillable = ['name', 'email', 'message'];
🧠 Step 2: Create a Feedback Controller
php artisan make:controller FeedbackController
In app/Http/Controllers/FeedbackController.php:
namespace App\Http\Controllers;
use App\Models\Feedback;
use Illuminate\Http\Request;
class FeedbackController extends Controller
{
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:100',
'email' => 'required|email',
'message' => 'required|string|min:10',
]);
Feedback::create($validated);
return back()->with('success', 'Thanks for your feedback!');
}
}
🛣 Step 3: Add the Route
In routes/web.php:
use App\Http\Controllers\FeedbackController;
Route::post('/feedback', [FeedbackController::class, 'store'])->name('feedback.store');
🎨 Step 4: Create the Modal Feedback Form Component
Create a new Vue component:resources/js/Components/FeedbackModal.vue
<template>
<div v-if="show" class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
<div class="bg-white p-6 rounded-lg w-full max-w-md shadow-xl relative">
<h2 class="text-xl font-bold mb-4">Submit Feedback</h2>
<form @submit.prevent="submit">
<div class="mb-3">
<label>Name</label>
<input v-model="form.name" type="text" class="border p-2 w-full" />
<div v-if="form.errors.name" class="text-red-500">{{ form.errors.name }}</div>
</div>
<div class="mb-3">
<label>Email</label>
<input v-model="form.email" type="email" class="border p-2 w-full" />
<div v-if="form.errors.email" class="text-red-500">{{ form.errors.email }}</div>
</div>
<div class="mb-3">
<label>Message</label>
<textarea v-model="form.message" class="border p-2 w-full"></textarea>
<div v-if="form.errors.message" class="text-red-500">{{ form.errors.message }}</div>
</div>
<div class="flex justify-between items-center">
<button type="button" @click="close" class="text-gray-600">Cancel</button>
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded">Send</button>
</div>
<div v-if="success" class="text-green-600 mt-3">{{ success }}</div>
</form>
</div>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
import { useForm, usePage } from '@inertiajs/vue3'
const props = defineProps({
show: Boolean,
})
const emit = defineEmits(['close'])
const form = useForm({
name: '',
email: '',
message: '',
})
const success = ref(null)
function submit() {
form.post('/feedback', {
onSuccess: () => {
success.value = 'Thank you for your feedback!'
setTimeout(() => {
form.reset()
close()
}, 1500)
},
})
}
function close() {
success.value = null
form.reset()
emit('close')
}
</script>
🧩 Step 5: Use the Modal in a Page
Let’s now display this modal on a page, like Dashboard.vue.
<template>
<div class="p-8">
<h1 class="text-2xl font-bold mb-6">Welcome to the Dashboard</h1>
<button @click="showModal = true" class="bg-green-600 text-white px-4 py-2 rounded">
Leave Feedback
</button>
<FeedbackModal :show="showModal" @close="showModal = false" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import FeedbackModal from '@/Components/FeedbackModal.vue'
const showModal = ref(false)
</script>
🧠 Step 6: Share Flash Messages (Optional)
To use flash messages, update app/Http/Middleware/HandleInertiaRequests.php:
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'flash' => [
'success' => fn () => $request->session()->get('success'),
],
]);
}
✅ Final Output
Now, when the user clicks the “Leave Feedback” button:
- A modal appears with a form
- The user submits feedback
- Laravel stores it in the database
- The modal shows a success message and closes automatically


Leave a Reply