A multiple v-model implementation for Vue2
Read about it here in detail https://dev.to/michaelolof_/multiple-v-model-for-the-rest-of-us-1pb8
$ npm install --save vue2-multiple-vmodels
In main.js file
import Vue from "vue"
import Vue2MultipleVModels from "vue2-multiple-vmodels";
Vue.use(Vue2MultipleVModels);
The library comes with 2 helper directives.
v-models
- Multiple 2 way binding for vue2v-model-destruct
- Destructure av-model
object and bind directly to its fields
The v-models directive gives you the power of multiple v-models just like in the new vue 3 feature.
You can create a component that supports v-models
like this
SelectInput.vue
<template>
<div class="select-input">
<select v-model="select" class="select-input__select">
<slot />
</select>
<input v-model="input" class="select-input__input" />
</div>
</template>
<script>
export default {
models: [
{ data: "select", event: "models:select" },
{ data: "input", event: "models:input" },
],
data() {
return {
select: undefined,
input: "",
}
},
watch: {
select(newVal) {
this.$emit("models:select", newVal);
},
input(newVal) {
this.$emit("models:input", newVal);
},
},
}
</script>
This component can then be used like this
<template>
<SelectInput v-models:input="amount" v-models:select="currency">
</template>
<script>
export default {
data() {
return {
input: 100,
currency: "GHS"
}
}
}
</script>
Caveats
- Only works with custom components.
v-models
relies on data not props. Props can still be used to sync data the traditional way, but we register thedata
and theevent
not theprop
- All
v-models
events must be of the format withmodels:<xxx>
Thev-models
directive checks for this. - Registeration of data and event is done in the
models
section when defining the component.models
must be an array.
Use full for existing/already defined components which emit objects.
Take a PhoneCountry
component which emits an object as shown below
PhoneCountry.vue
<template>
<PhoneCountry v-model="phone">
</template>
<script>
export default {
data() {
return {
phone: {
country: "Nigeria",
dial: "234",
phone: "234123456789"
}
}
}
}
</script>
v-model-destruct
allows you bind (2-way binding) directly to any of the fields you're interested in. E.g
<template>
<PhoneCountry v-model-destruct:country="country" v-model-destruct:phone="phone" />
</template>
<script>
export default {
data() {
return {
country: "Nigeria",
phone: "234123456789"
}
}
}
</script>
Caveats
- Only works with Components that emit objects or the value of v-model is an object.
- 2-way binding is limited to component design. If your component (E.g PhoneCountry) is not designed to track changes in object fields (E.g country field), changes made when you update country from the parent component might not update the child (PhoneCountry) component.