Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

hmzak's avatar
Level 5

Pass Dynamic Page Headers to a Globally Persistent Layout

I have a TheLayout.vue component in my Vue.js and Inertia.js web application. When I wrap a child component with <the-layout>, I can pass slots for a page header and subheader like this:

<template>
  <the-layout>
    <template #page-header>Login</template>
    <template #page-sub-header
      >Login here</template
    >

    <div class="container mt-5">
      <h1>Login</h1>
    </div>
  </the-layout>
</template>

However, I want to make TheLayout.vue a persistent layout, so I’ve set it up globally in app.js. This allows me to apply the layout automatically without wrapping every child component with <the-layout> tag.

Now the problem is how can I pass different page headers and subheaders to TheLayout.vue from child component pages as im not manually wrapping them anymore?

Here is the setup

Thelayout.vue

Login.vue

<template>

//This is login component and i want to pass page header "Login" from here.
//Likewise from all other page components. 
  
    <div class="container mt-5">
      <h1>Login</h1>
    </div>
</template>

app.js

import { createApp, h } from 'vue'
import { createInertiaApp, Link } from '@inertiajs/vue3'
import TheLayout from './Layout/TheLayout.vue';


createInertiaApp({
    title:(title)=>`My App ${title}`,
    resolve: (name) => {
    const pages = import.meta.glob('./Pages/**/*.vue', { eager: true });
    const page = pages[`./Pages/${name}.vue`];

    page.default.layout = page.default.layout || TheLayout;
    return page;
  },
    setup({ el, App, props, plugin }) {
    createApp({ render: () => h(App, props) })
      .use(plugin)
      .component('inertia-link',Link)
      .mount(el)
  },
})

I may be able to use provide/inject to pass the headers, but I’m looking for a better solution that doesn’t require setting up provide and inject in every child component just to configure the page header and sub-header.

0 likes
1 reply
LaryAI's avatar
Level 58

To achieve dynamic page headers and subheaders in a globally persistent layout without manually wrapping each child component, you can use Vue's provide/inject mechanism. However, since you prefer not to set up provide/inject in every child component, you can use a mixin or a custom plugin to handle this more elegantly.

Here's a solution using a mixin:

  1. Create a mixin to handle page headers and subheaders:

Create a file named pageHeaderMixin.js:

export default {
  data() {
    return {
      pageHeader: '',
      pageSubHeader: ''
    };
  },
  created() {
    if (this.$options.pageHeader) {
      this.pageHeader = this.$options.pageHeader;
    }
    if (this.$options.pageSubHeader) {
      this.pageSubHeader = this.$options.pageSubHeader;
    }
  }
};
  1. Update TheLayout.vue to use the mixin:

Modify TheLayout.vue to use the mixin and display the headers:

  1. Set headers in child components:

In your child components, you can now set the pageHeader and pageSubHeader options:

For example, in Login.vue:

<template>
  <div class="container mt-5">
    <h1>Login</h1>
  </div>
</template>

<script>
export default {
  pageHeader: 'Login',
  pageSubHeader: 'Login here'
};
</script>
  1. Ensure the mixin is globally available:

If you want to make sure the mixin is available globally, you can register it in your app.js:

import { createApp, h } from 'vue';
import { createInertiaApp, Link } from '@inertiajs/vue3';
import TheLayout from './Layout/TheLayout.vue';
import pageHeaderMixin from './mixins/pageHeaderMixin';

createInertiaApp({
  title: (title) => `My App ${title}`,
  resolve: (name) => {
    const pages = import.meta.glob('./Pages/**/*.vue', { eager: true });
    const page = pages[`./Pages/${name}.vue`];

    page.default.layout = page.default.layout || TheLayout;
    page.default.mixins = page.default.mixins || [];
    page.default.mixins.push(pageHeaderMixin);

    return page;
  },
  setup({ el, App, props, plugin }) {
    createApp({ render: () => h(App, props) })
      .use(plugin)
      .component('inertia-link', Link)
      .mount(el);
  },
});

With this setup, you can dynamically set page headers and subheaders in your child components without manually wrapping them with <the-layout>. The mixin will handle the data and pass it to the layout component.

Please or to participate in this conversation.