Laravel Jetstream + Inertia is an amazing foundation for building modern apps using Vue (auth, basic ui kit) without the struggles of SPA. This article assumes you followed the installation steps on Laravel Jetstream's website for Inertia and you are ready to jump in but you're a little new to Inertia or Vue.
How do I work with Inertia?
Inertia may seem very different at first, but nothing actually changes with how you think about things like routes, controllers and views within Laravel. You still add a route to web.php, point it to a controller and return a view.
The main difference is that you return Inertia::render()
from a controller. This response will ultimately render a Vue component and pass it data defined in our Laravel controllers.. solving a complexity of using Vue + Laravel.
Route::get('posts', 'PostsController@index')->name('posts.index');
public function index()
{
$posts = Post::all();
return Inertia::render('Posts/Index', [
'posts' => $posts
]);
}
Where do I put views?
There is a resources/js/Pages
folder created when you installed Jetstream. Add Posts/Index.vue
within that folder to handle Inertia::render('Posts/Index')
. Similar to view('posts.index')
Where are my changes when I refresh?
Since we are using Vue, we need to compile our vue components / pages or the changes we make in .vue files will not show in the browser. It basically just means npm install
to install dependencies and npm run watch
to watch files for changes and re-compile. Luckily Laravel makes this user friendly. docs
How do I access the view data?
The vue component will automatically receive the data we added to Inertia::render()
within our controller just like when we say view()->with()
. The key differences are we need to add each variable as a property in props
so vue is aware and use vue's template syntax instead of Blade.
resources/js/Pages/Posts/Index.vue
<template>
<app-layout>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Posts
</h2>
</template>
<div>
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
<div v-for="post in posts" :key="post.id">
{{ post.title }}
</div>
</div>
</div>
</app-layout>
</template>
<script>
import AppLayout from '@/Layouts/AppLayout'
export default {
props: ['posts'],
components: {
AppLayout
},
}
</script>
- What is the
@
in the import? It's an alias defined in webpack.mix.js - What is #header? Shorthand for Vue's component slot
What is <app-layout>
?
Jetstream comes with a lot of really useful vue components for things like form elements and modals, located in resources/js/Jetstream
, but <app-layout>
is in resources/js/Layouts
and is the main shell that renders this:
Adding your content within this vue component means you'll automatically have navigation in place and a nice starting point for your layout.
How do I link to my page?
Jetstream installs Ziggy to handle using named routes within Inertia / Vue. Using Ziggy's route
method & the <inertia-link>
component:
<inertia-link :href="route('posts.index')">
Posts
</inertia-link>
To add a link to the main navigation within the <app-layout>
, open the layout file within resources/js/Layouts/App.vue
and add a link:
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
<jet-nav-link :href="route('dashboard')" :active="route().current('dashboard')">
Dashboard
</jet-nav-link>
<jet-nav-link :href="route('posts.index')" :active="route().current('posts.index')">
Posts
</jet-nav-link>
</div>
(<jet-nav-link>
is a component in resources/js/Jetstream
)
How do I submit forms?
Inertia provides a really helpful way of using ajax to submit forms. First, use v-model
to connect your inputs to the vue state defined in the data()
section of your vue component and call a method using the @submit
event handler.
<template>
<form @submit.prevent="submit">
<label for="title">Title:</label>
<input id="title" v-model="form.title" />
<label for="body">Body:</label>
<input id="body" v-model="form.body" />
<button type="submit">Submit</button>
</form>
</template>
<script>
export default {
data() {
return {
form: {
title: null,
body: null
},
}
},
methods: {
submit() {
this.$inertia.post('/posts', this.form)
},
},
}
</script>
How does Inertia render Vue?
Laravel Jetstream sets the root view to app.blade.php in app/Http/Middleware/HandleInertiaRequests
which is rendering:
<body class="font-sans antialiased">
@inertia
</body>
Which is outputting the root div Vue will attach to and passing it data:
<div id="app" data-page="{{ json_encode($page) }}"></div>
How is resources/js/Pages defined?
This mapping happens in resources/app.js
resolveComponent: (name) => require(`./Pages/${name}`).default,
Conclusion
Hope you found that helpful. I plan to write more about Jetstream as I find it to be extremely powerful. If you have feedback, I'd love to hear it on twitter.
Top comments (4)
can I install other component libraries to use in my view? like for example vue bootstrap?
how do I view a blade without using Inertia
Es recomendado cambiar la plantilla frontent de Jetstream por una en particular?, o de manera forzada debemos de utilizar la por default?
I want to ask can I use packages like Spatie role Faker with Inertia