Reputation: 278
I try to get this to work
<component v-if="!pending" :is="dynComponent" />
In Nuxt 2 it was no problem, but in Nuxt 3 (Vue 3 ?) it doesn't seem so easy.
The variable dynComponent
is filled with the name of the component in the course of the process (myComponent).
As in Nuxt 2, I import the corresponding component with import myComponent from "@/layouts/myComponent.vue"
. The error is probably there.
I read in the docs that the use of resolveComponent
helper is required. I've also tried as described...but without success. (Dynamic components)
I don't get any error messages either. Nothing happens.
Can someone explain me how to use dynamic components in Nuxt 3?
Upvotes: 12
Views: 17138
Reputation: 53
For anyone else stumbling on this, I use the following solution, which is a lot more "dynamic" :
<script setup>
const props = defineProps(['data'])
const is = computed(() => {
return defineAsyncComponent(
() => import(`@/components/template/${props.data.folder}/${props.data.filename}.vue`)
)
})
</script>
<template>
<div>
<component :is="is" v-if="is" />
</div>
</template>
The import needs to follow the standard rules for the path to resolve correctly. You can't just drop the whole file path into the import.
Obviously, all you need to do is modify the string interpolation to match your file structure. I have previously added multiple if statements into the computed property to deal with different file path structures before and it works fine.
Hope it helps!
Upvotes: 3
Reputation: 198
As I saw some other people to continue to ask and I struggled with this as well, here's my proposed solution after getting it to work. You can adapt it to whatever is needed, but I tried to cover all bases with this example.
<script setup>
import { MyComponentA, MyComponentB } from '#components'
// type can be 'a' or 'b'
const props = defineProps(['type', 'data'])
const typeComponent = computed(() => {
const map = {
a: MyComponentA,
b: MyComponentB,
}
return map[props.type]
})
</script>
<template>
<component :is="typeComponent" :data="data" />
</template>
With this, you can still benefit from all the Nuxt Magic regarding component naming and so on. So if your component lies in components/my/component/A.vue
it will work as expected.
Upvotes: 0
Reputation: 46824
This is how you should write your dynamic component.
<script setup>
const yolo = resolveComponent('Yolo')
const bob = resolveComponent('Bob')
const boolean = ref(true)
</script>
<template>
<div>
<div>{{ boolean }}</div>
<component :is="boolean ? yolo : bob" />
<button @click="boolean = !boolean">toggle</button>
</div>
</template>
With this kind of structure
Upvotes: 31