Back to Course |
Vue Inertia + Laravel 11: From Scratch

New "About" Page with Links Menu

Now, let's talk about links in Inertia. What do I mean by links?Currently, we only have the list of posts. Let's create another static page: for example, "About us". We will create two links above the table to link between the pages, and you will see the benefit of Inertia in terms of the SPA functionality.


Creating a Page

First, let's create a new Vue component and add some text.

There are no Artisan commands to create Vue components. You have to do that manually.

resources/js/Pages/About.vue:

<template>
<div>About us</div>
</template>

Because this page is static, we can define Route similar to how we would do if defining Route only for a view.

routes/web.php:

Route::view('/', 'dashboard')->name('dashboard');
 
Route::get('posts', [PostController::class, 'index']);
Route::inertia('about', 'About')->name('about');

And now, when we visit the /about page, we can see the text from About Vue component.


Adding Links

Now, let's add the links.

resources/js/Posts/Index.vue:

// ...
 
<template>
<div class="mb-4">
<a class="mr-2" href="/posts">Posts</a>
<a href="/about">About</a>
</div>
 
<table class="min-w-full divide-y divide-gray-200 border">
 
// ...

But, after clicking on the About in the Network tab, we can see that the page was fully reloaded with all the assets, which isn't SPA.

Instead of using a tag we must use the Link from Inertia.

resources/js/Posts/Index.vue:

<script setup>
import { Link } from '@inertiajs/vue3';
 
const props = defineProps({
posts: {
type: Object,
required: true
}
})
</script>
 
<template>
<div class="mb-4">
<a class="mr-2" href="/posts">Posts</a>
<a href="/about">About</a>
<Link class="mr-2" href="/posts">Posts</Link>
<Link href="/about">About</Link>
</div>
 
<table class="min-w-full divide-y divide-gray-200 border">
 
// ...

For now, let's copy these links to the About page.

resources/js/Pages/About.vue:

<script setup>
import { Link } from '@inertiajs/vue3';
</script>
 
<template>
<div class="mb-4">
<Link class="mr-2" href="/posts">Posts</Link>
<Link href="/about">About</Link>
</div>
 
<div>About us</div>
</template>

Now, after refreshing the page, all the assets are loaded, but only the Inertia component is reloaded after going between pages.

Pages are now loading as SPA.


Route Names with Ziggy

Next, let's examine route naming. It is much more convenient to call routes by their names. First, let's add names to the routes.

routes/web.php:

Route::view('/', 'dashboard')->name('dashboard');
 
Route::get('posts', [PostController::class, 'index'])->name('posts.index');
Route::inertia('about', 'About')->name('about');

Now, where we added links instead of hard-coding them, we should be able to call them the same way as in a Blade file. By default, it is impossible, but a package tighten/ziggy gives this ability. Let's install this package.

composer require tightenco/ziggy

Then we must add the @routes Blade directive to the main layout (before_ your application's JavaScript). Lastly, we need to use Ziggy in the Vue.

resources/js/app.js:

import './bootstrap';
 
import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/vue3'
import { ZiggyVue } from '../../vendor/tightenco/ziggy'
 
createInertiaApp({
resolve: name => {
const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
return pages[`./Pages/${name}.vue`]
},
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin)
.use(ZiggyVue)
.mount(el)
},
})

Now, we can use the route() helper in the Vue components. When defining links with the route() helper, the href must be prefixed with the : (colon).

resources/js/Pages/Posts/Index.vue:

// ...
<div class="mb-4">
<Link class="mr-2" href="/posts">Posts</Link>
<Link href="/about">About</Link>
<Link class="mr-2" :href="route('posts.index')">Posts</Link>
<Link :href="route('about')">About</Link>
</div>
 
// ...

resources/js/Pages/About.vue:

// ...
<div class="mb-4">
<Link class="mr-2" href="/posts">Posts</Link>
<Link href="/about">About</Link>
<Link class="mr-2" :href="route('posts.index')">Posts</Link>
<Link :href="route('about')">About</Link>
</div>
 
// ...

After visiting Posts or the About page visually, there is no difference, and going through pages, the result is the same. Only now, we're referencing the routes by names, so if, in the future, the endpoint for the route changes, you won't need to go through every page and change the URL manually.