Flash notifications with Inertia, Laravel and Vue

September 25th, 2024

In this article, we'll go through every step to getting flash notifications working in your Inertia apps when using Laravel and Vue, including building our own plugin to keep everything nice and clean.

Here's what the end result will look like once we're done:

blog/x8Hqg5g2tCzmIccQSBfWbxpCrL8DZrr9JSet1pvN.gif

There's no particular setup required before we get started. As long as you're running an Inertia app with Laravel and Vue, everything here should work (perhaps with a few tweaks). For this article, I'm using the Laravel Breeze starter kit with the Inertia Vue stack. If you'd like to follow along exactly, create a fresh project with Breeze!

Ok, so the process of flashing a message doesn't change much from what we'd typically do. Let's figure that out first.

Within any of your controllers, flash a message and redirect back. In my case, I've created a specific ActionController just to demonstrate this.

class ActionController extends Controller
{
    public function __invoke()
    {
        return back()->with('flash', [
            'title' => 'That worked!',
            'type' => 'success'
        ]);
    }
}

Notice I've added a title and a type to an array in this flash notification. These are completely flexible, and you can change what you send to the client later.

Here's the route for this action:

Route::post('/action', ActionController::class)->middleware(['auth', 'verified'])->name('action');

To trigger this flash notification, I updated the Dashboard.vue page to POST through to our new route:

<script setup>
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import { Head, router } from '@inertiajs/vue3';
</script>

<template>
    <Head title="Dashboard" />

    <AuthenticatedLayout>
        <template #header>
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">Dashboard</h2>
        </template>

        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <div class="p-6 text-gray-900">
                        <button v-on:click="router.post('/action')">Some action</button>
                    </div>
                </div>
            </div>
        </div>
    </AuthenticatedLayout>
</template>

Once you're able to make a request through to the action you want, it's time to share this flash data globally.

To access the flashed data, we'll need to share it globally so that potentially all pages, components and JavaScript files can access it.

That's a job for the HandleInertiaRequests middleware. Open it up, and add the flashed session data to the share method:

public function share(Request $request): array
{
    return [
        ...parent::share($request),
        'auth' => [
            'user' => $request->user(),
        ],
        'flash' => session('flash'),
    ];
}

There's no real structure to this right now since we want to be able to pass any data in this array to our client.

Let's think about when we need to read the global flash data we shared in HandleInertiaRequests.

Once an action happens, you're likely redirecting the user back to the previous page or elsewhere. So, the common event we're looking for is when the Inertia router has finished a request.

This is a premium article
Members get access to all articles, plus hundreds of screencasts.
Check it out
Already a member? Sign in to continue

Using Inertia's router, we're able to hook into events to perform actions like this:

import { router } from '@inertiajs/vue3'

router.on('finish', () => {
    //
})

Look again at that dot. That's here. That's home. That's us. On it everyone you love, everyone you know, everyone you ever heard of, every human being who ever was, lived out their lives.

Author
Alex Garrett-Smith
Share :

Comments

No comments, yet. Be the first!