Getting started with Inertia.js

What is Inertia.js

Inertia is a new approach to building classic server-driven web apps. Inertia allows you to create fully client-side rendered, single-page apps, without much of the complexity. And inertia has no client side routing, does not require an API also.

If we say simply, you create controllers, get the data from the database and render views.

Installation

Server-side setup

Install server-side adapter using composer

composer require inertiajs/inertia-laravel

Setup the root template

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
    <link href="{{ mix('/css/app.css') }}" rel="stylesheet" />
    <script src="{{ mix('/js/app.js') }}" defer></script>
  </head>
  <body>
    @inertia
  </body>
</html>

@inertia directive is a helper that creates a root <div> with an id of app that contains the page information and it tells Laravel that the views are generated using Inertia.

Client-side setup

setup the client-side adapter using these commands:

npm install @inertiajs/inertia @inertiajs/inertia-vue

or

yarn add @inertiajs/inertia @inertiajs/inertia-vue

update the resources/js/app.js

import { InertiaApp } from '@inertiajs/inertia-vue'
import Vue from 'vue'

Vue.use(InertiaApp)

const app = document.getElementById('app')

new Vue({
  render: h => h(InertiaApp, {
    props: {
      initialPage: JSON.parse(app.dataset.page),
      resolveComponent: name => require(`./Pages/${name}`).default,
    },
  }),
}).$mount(app)

Define the routes

For example:

I am going to discuss index view of users form and we can define the following route in web.php

Route::get('/users','\App\Http\Controllers\UsersController@index');

Create a controller

class UsersController extends Controller
{
    public function index(Request $request): \Inertia\Response
    {

        $users = User::when($request->get('search') ?? '', function ($query, $search) {
            $query->where('full_name', 'like', "%{$search}%");
        })
            ->orderBy('id', 'ASC')
            ->paginate('10')
            ->only('id', 'full_name', 'email', 'phone', 'country', 'investor_type');

        return Inertia::render('Users/Index', ['users' => $users]);
    }
}

We can create a controller using php artisan:make controller UsersController And render function is used for making inertia response. This function uses components and data.

Create a page(view) of index

After creating UsersController, we can create the index component under resources/js/Pages/Users. Assume the filename to be Index.vue, following code shows the contents of Index.vue

<template>
    <layout>
        <div class="container">
           <div class="col-6">
                <form @submit.prevent="search">
                    <div class="input-group mb-3">
                        <input type="text" v-model="q" class="form-control" placeholder="Search...">
                        <button class="btn btn-outline-secondary" type="submit" id="button-addon2">Search</button>
                    </div>
                </form>
            </div>
            <table class="table table-striped">
                <thead>
                <tr class="bg-gray-100">
                    <th scope="col">Id</th>
                    <th scope="col">Full Name</th>
                    <th scope="col">Email</th>
                    <th scope="col">Phone</th>
                    <th scope="col">Country</th>
                    <th scope="col">Investor Type</th>
                    <th scope="col">Actions</th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="user in users.data" :key="user.id">
                    <td>{{ user.id }}</td>
                    <td>{{ user.full_name }}</td>
                    <td>{{ user.email }}</td>
                    <td>{{ user.phone }}</td>
                    <td>{{ user.country }}</td>
                    <td>{{ user.investor_type }}</td>
                </tr>
                </tbody>
            </table>

            <pagination :links="users.links" />

        </div>
    </layout>
</template>

<script>
import Layout from "../../Shared/Layout";
import Pagination from "../../Shared/Pagination";

export default {
    components: { Layout,Pagination},
    props: {
        users: Object,
    },
    data() {
        return {
            q: '',
            form: {
                full_name: null,
                email: null,
                phone: null,
                country: null,
                investor_type: null,
            },
        }
    },
    mounted() {
        console.group('Users');
        console.log(this.users.links);
        console.log(this.users.data);
        console.groupEnd();
    },
    methods: {
        search() {
            this.$inertia.get(`/users?search=${this.q}`)
        }
    }
}
</script>

Create the layouts of page

In this example, I use Layout component that comes from resources/js/Shared/Layout.vue

<template>
    <main>
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            Users
        </h2>
        <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
            <button class="navbar-toggler" type="button" data-toggle="collapse"
                    data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>

            <div class="hidden md:block">
                <div class="ml-10 flex items-baseline space-x-4">
                  <inertia-link href="/users"
                                  class="bg-black-900 text-black-50 px-3 py-2 rounded-md text-sm font-medium">Users
                    </inertia-link>
                </div>
            </div>
        </nav>
        <article>
            <slot/>
        </article>
    </main>
</template>

<script>
export default {
    inject: ['page'],
}
</script>

That's all we have to do to create simple index view of users using inertia.js. If you want more information about inertia.js please refer the official documentation:


Related articles

Signature Pad with Alpine.js

The post describes the implementation of signature pads with Alpine.js. It also discusses how to integrate it with laravel livewire.