Custom Components with v-model
Introduction
Often times we have to create some components which perform some actions/operations on data and we require that in the parent component. Most of the times vuex would be a better solution, but component in cases where the child component's behavior has nothing to do with application state, for instance: A range-slider, date/time picker, file reader Having individual stores for each component each time they get used gets complicated.
Remarks
To have v-model on a component you need to fulfil two conditions.
1. It should have a prop named 'value'.
2. It should emit an input event with the value expected by the parent components.
<component v-model='something'></component>
is just syntactic sugar for
<component
:value="something"
@input="something = $event.target.value"
>
</component>
Examples
v-model on a counter component
Here counter is a child component accessed by demo which is a parent component using v-model.
// child component
Vue.component('counter', {
template: `<div><button @click='add'>+1</button>
<button @click='sub'>-1</button>
<div>this is inside the child component: {{ result }}</div></div>`,
data () {
return {
result: 0
}
},
props: ['value'],
methods: {
emitResult () {
this.$emit('input', this.result)
},
add () {
this.result += 1
this.emitResult()
},
sub () {
this.result -= 1
this.emitResult()
}
}
})
This child component will be emitting result each time sub() or add() methods are called.
// parent component
new Vue({
el: '#demo',
data () {
return {
resultFromChild: null
}
}
})
// parent template
<div id='demo'>
<counter v-model='resultFromChild'></counter>
This is in parent component {{ resultFromChild }}
</div>
Since v-model is present on the child component, a prop with name value was sent at the same time, there is an input event on the counter which will in turn provide the value from the child component.