N
Nuxt2mo ago
Wicker

Dynamic v-model with component :is

Hello i have this use case in my mind. Let's assume i have a list of components like this ( For context this is a modal with customer info reviews, product bought etc)
const componentMap = {
Products: ProductsPage,
Reviews: ReviewsPage,
etc...
};
const componentMap = {
Products: ProductsPage,
Reviews: ReviewsPage,
etc...
};
And use component :is like this
<component
:is="componentMap[componentName]"
:modalOpen="modalOpen"
:title="tile"
v-model:dynamicKey="data"
/>
<component
:is="componentMap[componentName]"
:modalOpen="modalOpen"
:title="tile"
v-model:dynamicKey="data"
/>
What i have in mind is if it would be possible to make the v-model key dynamic depending on the component for example after refactoring the componentMap
const componentMap = {
Products: {component:ProductsPage,modelKey:"products",values:products.value},
Reviews: {component:ReviewsPage,modelKey:"reviews",values:reviews.value},
etc...
};
const componentMap = {
Products: {component:ProductsPage,modelKey:"products",values:products.value},
Reviews: {component:ReviewsPage,modelKey:"reviews",values:reviews.value},
etc...
};
Atm i have all the v-models which it works but idk if it is the best approach
<component
:is="componentMap[componentName]"
:modalOpen="modalOpen"
:title="tile"
v-model:products="productData"
v-model:reviews="reviewData"
/>
<component
:is="componentMap[componentName]"
:modalOpen="modalOpen"
:title="tile"
v-model:products="productData"
v-model:reviews="reviewData"
/>
2 Replies
kapa.ai
kapa.ai2mo ago
Hi @Wicker. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To implement dynamic v-model bindings with the :is directive in Nuxt 3, you can use a combination of computed properties and the v-bind directive. Here's how you can approach this: 1. First, define your componentMap with the structure you proposed:
const componentMap = {
Products: { component: ProductsPage, modelKey: "products", values: products.value },
Reviews: { component: ReviewsPage, modelKey: "reviews", values: reviews.value },
// ...
};
const componentMap = {
Products: { component: ProductsPage, modelKey: "products", values: products.value },
Reviews: { component: ReviewsPage, modelKey: "reviews", values: reviews.value },
// ...
};
2. Create a computed property that returns the current component's configuration:
const currentComponent = computed(() => componentMap[componentName]);
const currentComponent = computed(() => componentMap[componentName]);
3. Use the v-bind directive with an object to dynamically set the v-model:
<component
:is="currentComponent.component"
:modalOpen="modalOpen"
:title="title"
v-bind="{ [`v-model:${currentComponent.modelKey}`]: currentComponent.values }"
/>
<component
:is="currentComponent.component"
:modalOpen="modalOpen"
:title="title"
v-bind="{ [`v-model:${currentComponent.modelKey}`]: currentComponent.values }"
/>
This approach allows you to dynamically set the v-model key based on the current component's configuration. However, it's important to note that using resolveComponent with variables is not supported in Nuxt 3. As mentioned in the Nuxt documentation (https://nuxt.com/docs/guide/directory-structure/components#dynamic-components), you should use one of the following approaches:
<template>
<component :is="conditionalComponent" />
<!-- This is OK ✅ -->

<component :is="getComponent(key)" />
<!-- This is OK ✅ -->
</template>

<script setup>
const conditionalComponent = computed(() => {
return condition ? resolveComponent('ComponentA') : resolveComponent('ComponentB')
})

const getComponent = (key) => {
return componentMap[key]
}
</script>
<template>
<component :is="conditionalComponent" />
<!-- This is OK ✅ -->

<component :is="getComponent(key)" />
<!-- This is OK ✅ -->
</template>

<script setup>
const conditionalComponent = computed(() => {
return condition ? resolveComponent('ComponentA') : resolveComponent('ComponentB')
})

const getComponent = (key) => {
return componentMap[key]
}
</script>
For your specific case, you might want to adjust your code to:
<template>
<component
:is="getComponent(componentName)"
:modalOpen="modalOpen"
:title="title"
v-bind="{ [`v-model:${getModelKey(componentName)}`]: getModelValues(componentName) }"
/>
</template>

<script setup>
const getComponent = (name) => componentMap[name].component;
const getModelKey = (name) => componentMap[name].modelKey;
const getModelValues = (name) => componentMap[name].values;
</script>
<template>
<component
:is="getComponent(componentName)"
:modalOpen="modalOpen"
:title="title"
v-bind="{ [`v-model:${getModelKey(componentName)}`]: getModelValues(componentName) }"
/>
</template>

<script setup>
const getComponent = (name) => componentMap[name].component;
const getModelKey = (name) => componentMap[name].modelKey;
const getModelValues = (name) => componentMap[name].values;
</script>
This approach should work well with Nuxt 3's component resolution system while still allowing you to dynamically set v-model bindings based on the component being rendered. Stack Overflow: Nuxt3 dynamic <component> (https://stackoverflow.com/questions/78319986) Nuxt Documentation: Dynamic Components (https://nuxt.com/docs/guide/directory-structure/components#dynamic-components) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@142400234444685312> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?