In the last lesson, we stopped before creating the login form. But, to create the login form, we need to get familiar with forms and how they work in Inertia in general.
We will do that based on another form: we will create the "Add new post" form and apply that form to the login form in the following lessons a bit later.
First, we need to create a Vue component where the form will be, then the route, and then we need to submit the form.
resources/js/Pages/Posts/Create.vue:
<script setup>import AppLayout from '../../Layouts/App.vue';import { Head } from '@inertiajs/vue3';</script> <template> <Head title="New Post" /> <AppLayout> Form here </AppLayout></template>
In the routes, we will transform the post route into a resource.
routes/web.php:
Route::get('posts', [PostController::class, 'index'])->name('posts.index'); Route::resource('posts', PostController::class); Route::inertia('about', 'About')->name('about');Route::inertia('login', 'Pages/Login')->name('login');
In the PostController
we need to return Inertia in the create()
method.
app/Http/Controllers/PostController.php:
use Inertia\Inertia;use Inertia\Response; class PostController extends Controller{ // public function create(): Response { return Inertia::render('Posts/Create'); } }
After visiting the posts/create
page, we see the page with the Form here
text.
Next, add a link above the posts table to the create post page.
resources/js/Pages/Posts/Index.vue:
<script setup>import AppLayout from '../../Layouts/App.vue';import { Head } from '@inertiajs/vue3'; import { Head, Link } from '@inertiajs/vue3'; const props = defineProps({ posts: { type: Object, required: true }})</script> <template> <Head title="Posts" /> <AppLayout> <Link :href="route('posts.create')" class="mb-4 inline-block rounded-md bg-blue-500 px-4 py-3 text-xs font-semibold uppercase tracking-widest text-white shadow-sm"> Add new post </Link> <table class="min-w-full border divide-y divide-gray-200"> // ...</template>
Now, let's add the form.
resources/js/Pages/Posts/Create.vue:
<script setup>import AppLayout from '../../Layouts/App.vue';import { Head } from '@inertiajs/vue3'; import { Head, Link } from '@inertiajs/vue3'; </script> <template> <Head title="New Post" /> <AppLayout> Form here <form @submit.prevent=""> <div> <div> <label for="title" class="block text-sm font-medium text-gray-700"> Title </label> <input v-model="form.title" type="text" id="title" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"> </div> <div class="mt-4"> <label for="content" class="block text-sm font-medium text-gray-700"> Content </label> <textarea v-model="form.content" id="content" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"></textarea> </div> </div> <div class="py-4 space-x-2"> <button type="submit" class="inline-block rounded-md bg-blue-500 px-4 py-3 text-xs font-semibold uppercase tracking-widest text-white shadow-sm"> Save post </button> <Link :href="route('posts.index')" class="inline-block rounded-md border border-gray-300 px-4 py-3 text-xs font-semibold uppercase tracking-widest shadow-sm"> Cancel </Link> </div> </form> </AppLayout></template>
In the form, we have a submit action where we will add the route later.
For each field, we have a v-model
with a prefix of form
. To define the v-model
, Inertia has a form helper that helps with the forms. First, we import the useForm
and then use it to define the form fields.
resources/js/Pages/Posts/Create.vue:
<script setup>import AppLayout from '../../Layouts/App.vue';import { Head, Link } from '@inertiajs/vue3'; import { Head, Link, useForm } from '@inertiajs/vue3'; const form = useForm({ title: '', content: ''}) </script> <template> // ...</template>
Now we can see the create form.
Before submitting the form in the front-end, let's add the back-end part in the Controller.
app/Http/Controllers/PostController.php:
use Illuminate\Http\Request;use Illuminate\Http\RedirectResponse; class PostController extends Controller{ // ... public function store(Request $request): RedirectResponse { Post::create([ 'title' => $request->title, 'content' => $request->content, ]); return redirect()->route('posts.index'); }}
To submit the form in the Vue component, we can use the form
from the Inertia form helper and send the post by providing the route.
resources/js/Pages/Posts/Create.vue:
// ... <template> <Head title="New Post" /> <AppLayout> <form @submit.prevent=""> <form @submit.prevent="form.post(route('posts.store'))"> // ... </form> </AppLayout></template>
Inertia's beauty is that we made a Laravel redirect after creating the post. Still, Inertia catches the redirect and keeps the SPA feeling by loading only the posts Vue component without loading all the assets.