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.
Preparation: React Component, Route and Controller
First, we need to create a React component where the form will be, then the route, and then we need to submit the form.
**resources/js/Pages/Posts/Create.jsx:
import AppLayout from '../../Layouts/AppLayout.jsx';import { Head, Link, useForm } from '@inertiajs/react'; export default function CreatePost() { return ( <AppLayout> <Head title="New Post" /> <div> Form here </div> </AppLayout> );}
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.
Add Link to the Form
Next, add a link above the posts table to the create post page.
resources/js/Pages/Posts/Index.jsx:
import AppLayout from '../../Layouts/AppLayout.jsx';import { Head } from '@inertiajs/react'; import { Head, Link } from '@inertiajs/react'; export default function PostsIndex({ posts }) { return ( <AppLayout> <Head> <title>Posts</title> </Head> <div> <Link href={route('posts.create')} className="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 className="min-w-full divide-y divide-gray-200 border"> // ... );};
Build The Form
Now, let's add the form.
resources/js/Pages/Posts/Create.jsx:
import AppLayout from '../../Layouts/AppLayout.jsx';import { Head, Link } from '@inertiajs/react'; export default function CreatePost() { return ( <AppLayout> <Head title="New Post" /> <div> Form here <form onSubmit={submit}> <div> <label htmlFor="title" className="block text-sm font-medium text-gray-700">Title</label> <input onChange={(e) => setData('title', e.target.value)} type="text" id="title" className="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 className="mt-4"> <label htmlFor="content" className="block text-sm font-medium text-gray-700">Content</label> <textarea onChange={(e) => setData('content', e.target.value)} type="text" id="content" className="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 className="mt-4 py-4 space-x-2"> <button type="submit" className="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')} className="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> </div> </AppLayout> );}
In the form, we have a submit action where we will add the route later.
Inertia has a form helper that helps with the forms. First, we import the useForm
and then use it to define and set the form fields.
resources/js/Pages/Posts/Create.jsx:
import AppLayout from '../../Layouts/AppLayout.jsx';import { Head, Link } from '@inertiajs/react'; import { Head, Link, useForm } from '@inertiajs/react'; export default function CreatePost() { const { data, setData, post, processing, errors, reset } = useForm({ title: '', content: '', }); return ( // ... );}
Now we can see the create form.
Submitting the 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->input('title'), 'content' => $request->input('content'), ]); return redirect()->route('posts.index'); }}
To submit the form in the React component, we can use the post
function from the Inertia form helper and send the post by providing the route.
resources/js/Pages/Posts/Create.jsx:
import AppLayout from '../../Layouts/AppLayout.jsx';import { Head, Link, useForm } from '@inertiajs/react'; export default function CreatePost() { const { data, setData, post, processing, errors, reset } = useForm({ title: '', content: '', }); const submit = (e) => { e.preventDefault(); post(route('posts.store')); }; return ( // ... );}
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 React component without loading all the assets.
#1 This should come before "Now we can see the create form."
Otherwise console shows submit is not defined.
#2 This I understand would be resolved by anyone who already know Laravel well enough - but just in case :
protected $fillable = ['title', 'content'];
has to be in app\Models\Post.php otherwise we'll get the error : Add [title] to the fillable property to allow mass assignment on [App\Post].Hello. Great tutorial. I have a form with fill-gap exercises (sentences and users must complete them). I want to submit a form, then highlight with green the correct ones and highlight the incorrect ones with red. In the example, after storing the post there is a redirection: return redirect()->route('posts.index'); how can I stay in the same form, receive the results, and update the UI? Thanks so much.
Return as validation errors maybe. Your question isn't something that can be answered here in the comment especially without more context
Thanks for your replying. I don't expect an error, I want to a proper response and update the UI. I just want to change the redirection in the store method for something that allow me stay in the same page and update it.
redirect()->back()
maybe. But if you know the route to which you want to get back why not use it? As I said it's a bit hard to answer in a comment hereIn your case a manual inertia visit might be even