Search code examples
global-variableslaravel-8vuejs3inertiajs

How can i define a global variable with Laravel 8, Inertia.js and Vue3?


I want to define a global variable or provide/inject or another way in default app.js file.

import { createApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/inertia-vue3";
import { InertiaProgress } from "@inertiajs/progress";
import Toast from "vue-toastification";
import "vue-toastification/dist/index.css";
import { useToast } from "vue-toastification";

const appName = window.document.getElementsByTagName("title")[0]?.innerText || "Laravel";
const toast = useToast();

createInertiaApp({
  title: (title) => `${title} - ${appName}`,
  resolve: (name) => require(`./Pages/${name}.vue`),
  setup({ el, app, props, plugin }) {
    return createApp({ render: () => h(app, props) })
      .use(Toast)
      .use(plugin)
      .mixin({ methods: { route } })
      .mount(el);
  },
});

I want to pass toast variable to all other components.

Here are some things I've tried so far:

  1. Vue3 Global Properties
createInertiaApp({
  title: (title) => `${title} - ${appName}`,
  resolve: (name) => require(`./Pages/${name}.vue`),
  setup({ el, app, props, plugin }) {
    app.config.globalProperties.$toast = toast; // Cannot read properties of undefined (reading 'globalProperties')

    return createApp({ render: () => h(app, props) })
      .use(Toast)
      .use(plugin)
      .mixin({ methods: { route } })
      .mount(el);
  },
});
  1. Also tried Provide/Inject in AppLayout.vue
  setup() {
    const toast = useToast();

    return { toast };
  },

  provide: {
    toast: this.toast,
  },

In one of the child components i tried to inject this.

inject: ["toast"]

i got the error 'injection "toast" not found.'


Solution

  • related to this answer (Use filter in Vue3 but can't read globalProperties) The config field belongs to the root instance not to the root component. The Vue.createApp(app) return the root instance and the myApp.mount('#app') return the root component. You should config your globals properties after createApp and before mount it, like this:

    import { createApp, h } from "vue";
    import { createInertiaApp } from "@inertiajs/inertia-vue3";
    import { InertiaProgress } from "@inertiajs/progress";
    import Toast from "vue-toastification";
    import "vue-toastification/dist/index.css";
    import { useToast } from "vue-toastification";
    
    const appName = window.document.getElementsByTagName("title")[0]?.innerText || "Laravel";
    const toast = useToast();
    
    createInertiaApp({
      title: (title) => `${title} - ${appName}`,
      resolve: (name) => require(`./Pages/${name}.vue`),
      setup({ el, app, props, plugin }) {
        const myApp = createApp({ render: () => h(app, props) })
          .use(Toast)
          .use(plugin)
          .mixin({ methods: { route } });
    
        // config global property after createApp and before mount
        myApp.config.globalProperties.$toast = toast;
    
        myApp.mount(el);
        return myApp;
      },
    });
    

    So you can use your global property inside all components:

    mounted() {
      console.log('global toast property: ', this.$toast);
    }