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 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.
- It should have a prop named ‘value’
- 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>
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.