2

In a fresh laravel installation i'm trying to make layout persistent following the inertia doc https://inertiajs.com/pages

app.js

require('./bootstrap');

// Import modules...
import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '@inertiajs/inertia-vue3';
import { InertiaProgress } from '@inertiajs/progress';
import AppLayout from '@/Layouts/AppLayout';

const el = document.getElementById('app');

createApp({
    render: () =>
        h(InertiaApp, {
            initialPage: JSON.parse(el.dataset.page),
            resolveComponent: name => import(`./Pages/${name}`)
              .then(({ default: page }) => {
                if (page.layout === undefined) {
                  page.layout = AppLayout
                }
                return page
              }),
        }),
})
    .mixin({ methods: { route } })
    .use(InertiaPlugin)
    .mount(el);

InertiaProgress.init({ color: '#4B5563' });

Dashboard.vue (here i replace the default app-layout wrapper by div)

<template>
    <div>
        <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-xl sm:rounded-lg">
                    <welcome />
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    import Welcome from '@/Jetstream/Welcome'

    export default {
        components: {
            Welcome,
        },
    }
</script>

While compiling i get this error :

Error: Codegen node is missing for element/if/for node. Apply appropriate transforms first.

I can't figure out what that means. Is there a reason why the default laravel app with jetstream and inertia doesn't use persistent layout?

mchev
  • 713
  • 1
  • 8
  • 22

2 Answers2

3

If the header slot is in AppLayout aka the persistent one, you cannot use this way (because there is no slot yet? I don't know but I know persistent layouts do mount after child components, this can be the culprit). As a solution, create another layout, ie PageLayout, with named slots and use that layout to build your dashboard and other pages:

AppLayout.vue

<template>
    <div>Persistent stuff...</div>
    <slot />
    <div>Persistent stuff...</div>
</template>

PageLayout.vue

<template>
    <slot name="header" />
    <slot name="content" />
    <div>PageLayout stuff...</div>
</template>

Dashboard.vue

<template>
    <PageLayout>
        <template #header>
            <h1>Dashboard</h1>
        </template>
        <template #content>
            <p>Welcome user!</p>
        </template>
    </PageLayout>
</template>

<script>
import AppLayout from 'AppLayout'
import PageLayout from 'PageLayout'

export default {
    layout: AppLayout, // Persistent layout
    components: {
        PageLayout // Regular layout
    }
</script>

There is an ongoing discussion here: https://github.com/inertiajs/inertia/issues/171

Mustafa Akçakaya
  • 1,069
  • 2
  • 11
  • 12
  • +1 for the work around. If you found any cleaner way to implement persistent layout in Laravel Jetstream, let us know (no work-around, default layouts, etc). I've also tried many different ways to implement without success so far. I'm also reverting to the standard layout structure proposed by Jetstream for now. – Frank Jun 30 '22 at 12:54
  • 1
    Marked as resolved since this work around is the best solution at the time of writing. – mchev Jul 01 '22 at 14:37
0

You need the app-layout as you need to extend from it <template #header>

  • 1
    Welcome new contributor. It would be great if you can improve your answer by e.g. an example and explaination why app-layout is needed in this case. – Starbax Jun 24 '21 at 11:50
  • Thanks, that's why the error is displayed but we can't make a persistent layout with this system. I finally gave up on the idea – mchev Jun 25 '21 at 07:39