Jarhakoz's avatar

Slot in persistent Inertia layout

I'm following the guide in https://inertiajs.com/pages#persistent-layouts And I'v placed a named slot in one of the layout components, <TopBar> And I'm then trying to use that named slot from the Inertia page component, but the problem is that the page component does not import the layout, hence it's persistent.

Now how does one use the slot int the (parent) layout component , from a Inertia page? My layout has a <SidePanel> and a <TopBar> and page goes into v-main slot

0 likes
8 replies
Sinnbeck's avatar

It might help us help you, if you show the code that isn't working. Is it vue or react?

Jarhakoz's avatar

Oh sorry, Laravel9, Vite, VUE3, Vuetify. The persistent layout is working just fine, but if I try to use a slot which is in the layout, from a page component, I get an error in compiler: TypeError: Cannot read properties of undefined (reading 'type')

<template>
<!-- use a slot called topmenu in SiteLayout -->
<template v-slot="topmenu"><h1>Hello</h1></template>
  <div>
    <H1>Welcome</H1>
    <p>Hello {{ user.name }}, welcome to your first Inertia app!</p>
  </div>
</template>

<script>
  import SiteLayout from './SiteLayout'
  import NestedLayout from './NestedLayout'
  export default {
    layout: [SiteLayout, NestedLayout],
    props: {
      user: Object,
    },
  }
</script>
tisuchi's avatar

@Jarhakoz The error message you're seeing suggests that the topmenu slot you're trying to use from your page component is not defined in the SiteLayout component. To fix this, you'll need to make sure that the topmenu slot is defined in the SiteLayout component's template.

1 like
Jarhakoz's avatar

No, there is in SiteLayout. I think the problem here is in the way this "persistent layout" thing is done, or in Inertia. We (meaning me) really need a better more complete example of using "persistent layout and default layout" than the one provided by Inertia here https://inertiajs.com/pages#default-layouts I ditched the part and moved everything to the old style, but no luck, same error.

The question remains, how does one use a named slot in layout (default, persistent layout), when it's not added as a parent from the Inertia page component?

4 likes
Oddman's avatar

@Jarhakoz Did you ever get this working? I don't think there's a way to do it...

MN-HettigerM's avatar

I use something like this:

<script setup lang="tsx">

// ...

defineOptions({
    layout: (h, page) => h(MainLayout, null, {
        default: () => [page],
        breadcrumbs: () => (
            <p>Hello World!</p>
        ),
    }),
});

// ...

</script>

It seems to work but it's not pretty. Would be nice if someone could share a better alternative.

MN-HettigerM's avatar

I refactored a bit and ended up with:

defineOptions({
    layout: SlottedMainLayout([
        { href: home(), label: "Home" },
        { href: login(), label: "Login" },
    ]),
});
// utilities.tsx

import MainLayout from "@/Layouts/MainLayout.vue";
import type { BreadcrumbsItem } from "@/entities.ts";
import Breadcrumbs from "@/Components/Breadcrumbs.vue";

export const SlottedMainLayout = (breadcrumbsItems: BreadcrumbsItem[]) => (h, page) => h(MainLayout, null, {
    default: () => [page],
    breadcrumbs: () => <Breadcrumbs items={breadcrumbsItems} />,
});

It still feels like a weird workaround. However, it seems to work and it's more readable than the initial version, so I'll keep it for now.

Shivamyadav's avatar

Could you please just share the example for composition api?

Please or to participate in this conversation.