8

I'm trying to build an application on Laravel 8.38 - InertiaJS 0.8.4 I'm using Vue 3 as my frontend stack.

I've multiple layouts which I need to register globally as Vue Component, so that I can use it in my application anywhere. I'm unable to do so, my code:

import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '@inertiajs/inertia-vue3';

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

const app = createApp({
    render: () =>
        h(InertiaApp, {
            initialPage: JSON.parse(el.dataset.page),
            resolveComponent: (name) => require(`./../Pages/${name}`).default,
        }),
})
    .mixin({ methods: { route } })
    .use(InertiaPlugin);

app.component('app-market', () => import('./../layouts/AppMarketLayout')); //trying to import layout

app.mount(el);

And inside the page I'm trying to call this layout component:

<template>
    <div>
        <app-market-layout></app-market-layout>
    </div>
</template>

Unable to fetch, no errors in console.

1
  • 2
    You've registered an app-market component, but your markup uses app-market-layout. Commented May 15, 2021 at 21:55

3 Answers 3

2

In Inertia JS, importing components globally is the same as using a normal Vue configuration.

In your app.js file, you need to import the component(either inline or at the top of the file), then add the component before mounting the vue instance. You can either do this as a mixin, or as a component.

So, in your case, the configuration should look like the below:

import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '@inertiajs/inertia-vue3';

//Import the component:
import AppMarket from "./../layouts/AppMarketLayout"; 

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

const app = createApp({
    render: () =>
        h(InertiaApp, {
            initialPage: JSON.parse(el.dataset.page),
            resolveComponent: (name) => require(`./../Pages/${name}`).default,
        }),
})
    .mixin({ methods: { route } })
    .mixin({ components: { AppMarket } }) // << Then tell the inertia 
             // instance to use the component. 
             // You can also add this to the other mixin declaration
    .use(InertiaPlugin)
    .mount(el);

Then, in your template, you can use the component like this:

<template>
    <app-market>
    </app-market>
</template>

I noticed in your original post you are trying to use the component as app-market-layout. You must import the component with that name if you plan to do that.

The configuration would look like this in app.js:

import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '@inertiajs/inertia-vue3';

//Import the component: Notice the component name change.
import AppMarketLayout from "./../layouts/AppMarketLayout"; 

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

const app = createApp({
    render: () =>
        h(InertiaApp, {
            initialPage: JSON.parse(el.dataset.page),
            resolveComponent: (name) => require(`./../Pages/${name}`).default,
        }),
})
    .mixin({ methods: { route } })
    .mixin({ components: { AppMarketLayout } }) // << Here the component name has Layout
    .use(InertiaPlugin)
   
    .mount(el);

Then in your template:

<template>
    <app-market-layout>
    </app-market-layout>
</template>
Sign up to request clarification or add additional context in comments.

Comments

1

I was having 2 layouts for backend(admin-panel) and frontend(website), achieved as follows. Using inertia default middleware file.

project/app/Http/Middleware/HandleInertiaRequests.php

class HandleInertiaRequests extends Middleware
{
    protected $rootView = 'app';

    public function rootView(Request $request)
    {
        if ($request->segment(1) == 'admin') {
            return 'admin';
        }

        return parent::rootView($request);
    }

    public function version(Request $request)
    {
        return parent::version($request);
    }

    public function share(Request $request)
    {
        return array_merge(parent::share($request), [
            //
        ]);
    }
}

project/resources/js/Shared/Frontend/Layouts/Layout.vue

<template>

    <Header />

    <slot />

    <Footer />

</template>

<script>
    import Header from '../Partials/Header'
    import Footer from '../Partials/Footer'
    export default {
        components: {
            Header,
            Footer
        },

        name: "FrontendLayout"
    }
</script>

project/resources/js/Pages/Frontend/Auth/Login.vue

<template>
    ...
</template>

<script>
    import Layout from '@/js/Shared/Frontend/Layouts/Layout';
    export default {
        
        layout: Layout,

        metaInfo: { title: 'Login' },

        data() {
            return {
                form: this.$inertia.form({
                    'email': '',
                    'password': '',
                    'remember': false
                })
            }
        },

        methods: {
            submit() {
                this.form.post(route('login.store'))
            }
        }
    }
</script>

Comments

1

In latest Inertia, Just import the 'Link' component and added .component("Link", Link) between .use() and .mount()

import { createApp, h } from 'vue';
import {createInertiaApp, Link} from '@inertiajs/inertia-vue3';
import { InertiaProgress } from '@inertiajs/progress'

createInertiaApp({
    resolve: name => {
        const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
        return pages[`./Pages/${name}.vue`]
    },
    setup({ el, App, props, plugin }) {
        createApp({ render: () => h(App, props) })
            .use(plugin)
            .component("Link", Link)
            .mount(el)
    },
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.