Tobi360
Tobi360

Reputation: 278

I can't use dynamic components in Nuxt 3

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

Answers (3)

davepiqch
davepiqch

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

Codebryo
Codebryo

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

kissu
kissu

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

enter image description here

Upvotes: 31

Related Questions