Subscribe on changes!

Cannot use string variable for <component :is="someVar"> with script-setup

avatar
Sep 3rd 2021

Version

3.2.8

Reproduction link

sfc.vuejs.org/

Steps to reproduce

See link to repro.

What is expected?

The HelloWorld component should be shown.

What is actually happening?

The HelloWorld component is not shown. No console error.


This doesn't work:

<template>
  <component :is="myComponent"></component>
</template>

<script setup>
import HelloWorld from './HelloWorld.vue'
const myComponent = 'HelloWorld'
</script>

Passing the object instead of the string works:

<script setup>
import HelloWorld from './HelloWorld.vue'
const myComponent = HelloWorld // Removed the quotes
</script>

But I'd expect the first snippet to work since it's possible to pass it as string in the following example

<script>
import HelloWorld from './HelloWorld.vue'

export default {
  components: {
    HelloWorld
  },
  setup() {
    const myComponent = 'HelloWorld'

    return {
      myComponent
    }
  }
}
</script>
avatar
Sep 3rd 2021

It is expected. Without the components option you don't have a chance to give the component a local name (string) and there's no need to do so.

avatar
Sep 3rd 2021

and there's no need to do so.

@Justineo This was a contrived example, but my actual use case is a dynamically generated form. I have a list of async components:

// ComponentsList.js:
import { defineAsyncComponent } from 'vue'

export default {
    CheckBox: defineAsyncComponent(() => import('./CheckBox.vue')),
    TextBox: defineAsyncComponent(() => import('./TextBox.vue')),
    ...
}

And generate the form using code similar to this:

<template>
    <component
        v-for="component in myListOfDesiredComponents"
        :key="component.controlId"
        :is="'Components.' + component.type"
        v-bind="component.model"
    ></component>
</template>

<script setup>
import Components from './ComponentsList.js'

const props = defineProps({
    myListOfDesiredComponents: Array // Example of item: { type: 'CheckBox', controlId: 'something-unique', model: { name: 'Foo' } }
})
</script>

The string being 'CheckBox' in this example. Indeed it works when using the components: Components option, but is there no way to make this work with script-setup?

avatar
Sep 16th 2021

@leboeuf I solved it by creating a map that goes from strings to the imported components.

import HelloWorld from './components/HelloWorld.vue'
import FooComp from './layouts/FooComp.vue'

export const compMap = new Map()
compMap.set("HelloWorld", HelloWorld)
compMap.set("FooComp", FooComp)

then you can use that and get the value instead of using it directly