[Vuejs]-Vue3 โ€“ Bind multiple named v-model dynamically

1๐Ÿ‘

You can build your own v-model like this:

<!-- parent component -->
<template>
<component :is="field.component" v-bind="field.props" @updateValue="onUpdateValue"></component>
</template>

<script lang="ts" setup>
function onUpdateValue(field: string, value: any){
  field.models[field] = value
}
</script>
<!-- child component -->
<template>
<input :value="somePropsField" @input="$emit('updateValue', 'somePropsField', $event)"></input>
</template>

In the child component, you emit an event called updateValue with a field name to update, and the value of that field. And in the parent component, you listen to that event and update the data accordingly

๐Ÿ‘คDuannx

0๐Ÿ‘

To whoever encounters the same need, you can add bindings for :<REF_NAME> and onUpdate:<REF_NAME>. The parent component will be in control of the child component model, it might not be the cleanest way to achieve it but it achieve the purpose.

I link an updated DEMO if needed

<script lang="ts" setup>
import { ref, reactive, shallowRef } from 'vue'
import MainRenderer, { FormField } from './MainRenderer.vue'
import Foo from './Foo.vue'
import Bar from './Bar.vue'


function defineNamedModel(name: string, model: Ref){
    // A generic function to avoid repeating code
    let binding = `:${name}`
    let updateCallback = `onUpdate:${name}` 
    return {
        [binding]: model,
        [updateCallback]:((v: any) => model.value = v)
    }
}

const inputFoo = ref('fooValue')
const inputBar = ref('barValue')
const foo = ref(false)
const bar = ref(false)

const fields: FormField[] = reactive([
    {
        name: "Foo - String Input Field",
        model: shallowRef(inputFoo),
        props: { class: 'dummy-class', placeholder: "Input A" },
        component: Foo
    },
    {
        name: "Bar - Multi Item Input Field",
        model: shallowRef(inputBar),
        props: { class: 'dummy-class', ...defineNamedModel('bar', bar)},
        component: Bar
    },
])


const action = async function () {
    console.log(fields)
}
</script>
๐Ÿ‘คWaligoo

Leave a comment