'Implementing route based models in Vue3 (Inertia.js)

I am following the following this guide, that shows how to enable "Route Based Modals" in Inertia.js.

The post is written for Vue2, and I am using Vue3 - and I am having some issues getting it to work.

This is my "Composable" for my "useModal" method:

//Composables/useModal.js
const useModal = {
    computed: {
        modalComponent() {
            return this.$page.props.modal
                ? () => import(`@/Pages/${this.$page.props.modal}`)
                : false
        }
    }
}

export { useModal }

I then declare it in my app.js file as per below:

//app.js
//...

import {useModal} from "@/Composables/useModal";

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

In my main layout, called AppLayout I have declared the Component:

<body>

<!-- Main elements are here, removed for clarity -->
<Component
        v-bind="$page.props"
        v-if="$root.modalComponent"
        :is="$root.modalComponent"
    />

</body>

Further, I have declared the modal() method in my AppServiceProvider:

public function boot()
{
    ResponseFactory::macro('modal', function ($modal) {
        inertia()->share(['modal' => $modal]);
    });
}

Now, I am trying to render a Vue component in a modal like so:

//FileController.php

public function show(File $file){
   \inertia()->modal('File/Show');

   return $this->index($file);
}

When linking to the modal component, the following Warning is issued:

[Vue warn]: Invalid VNode type: undefined (undefined) at <Anonymous key=0 ...



Solution 1:[1]

I ended up fixing this by using defineAsyncComponent instead:

//Composables/useModal.js
import {defineAsyncComponent} from "vue";

const useModal = {
    computed: {
        modalComponent() {
            return this.$page.props.modal
             ? defineAsyncComponent(() => import(`@/Pages/${this.$page.props.modal}`))
                : false
        }
    }
}

export { useModal }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 oliverbj