How To Add Two-Way Data Binding to Custom Components in Vue.js
Table of Contents
Introduction #
In this article, you will learn about how to add the v-model
directive for custom components in Vue.js. While the v-model
directive is a powerful asset to add two-way data binding in vanilla Vue.js components, support for custom components isn’t as exercised.
Prerequisites #
An understanding of two-way data binding in Vue.js is suggested but not required. To learn more about two-way data binding, check out our How To Use v-model
for Two-Way Binding in Vue.js tutorial.
v-model
Directive>Implementing the v-model
Directive
#
To understand how to implement v-model
support in your components, you need to understand how it works under the hood. The v-model="prop"
value is shorthand for :value="prop" @input="prop = arguments[0]"
.
As such, to make your component compatible with the v-model
directive, it must accept the :value
and @input
attributes to add and emit a value when a user interacts with your Vue.js application.
In your DatePicker.vue
file, create a custom component that accepts a month
and year
value in an object. The :value
and @input
attributes will represent the values referenced in your component. Set a template with inputs for your month
and year
values:
DatePicker.vue
<template>
<div class="date-picker">
Month: <input type="number" ref="month-picker" :value="value.month" @input="updateDate()"/>
Year: <input type="number" ref="year-picker" :value="value.year" @input="updateDate()"/>
</div>
</template>
<script>
export default {
props: ['value'],
methods: {
updateDate() {
this.$emit('input', {
month: +this.$refs.monthPicker.value,
year: +this.$refs.yearPicker.value
})
}
}
};
</script>
Within the script
tag, your custom method updateDate()
applies the .$emit()
public instance property to update the values in month
and year
based on user input.
To use your custom component in other Vue.js files, set the v-model
directive to bind and add values from your month
and year
properties in your WrapperComponent.vue
file:
WrapperComponent.vue
<template>
<div class="wrapper">
<date-picker v-model="date-picker"></date-picker>
<p>
Month: {{date.month}}
Year: {{date.year}}
</p>
</div>
</template>
Within the script
tag, import your custom component and insert it into the components
property. This will employ the functionality contained in your DatePicker
component into your WrapperComponent.vue
file:
WrapperComponent.vue
<script>
import DatePicker from './DatePicker.vue';
export default {
components: {
DatePicker
},
data() {
return {
date: {
month: 1,
year: 2017
}
}
}
})
</script>
The data()
model stores and returns the values in your month
and year
properties.
To review, two-way binding with custom components requires the attributes :value
and @input
to add and emit an updated date in one call.
v-model
in Advanced Components>Practicing v-model
in Advanced Components
#
By using one or more computed properties, you can integrate data, such as strings, into a format input that elements can manage. This is often used with advanced custom components that handle a variety of potential input formats.
In your StringDatePicker.vue
file, create a custom component that passes a string with the structure m/yyyy
. Set your :value
and @input
attributes into your inputs to accept and update values from your custom component:
StringDatePicker.vue
<template>
<div class="date-picker">
Month: <input type="number" ref="monthPicker" :value="splitDate.month" @input="updateDate()"/>
Year: <input type="number" ref="yearPicker" :value="splitDate.year" @input="updateDate()"/>
</div>
</template>
By using a computed property, in this case splitDate
, you can split and return the input string into an object with month
and year
properties:
[label StringDatePicker.vue]
<script>
export default {
props: ['value'],
computed: {
splitDate() {
const splitValueString = this.value.split('/');
return {
month: splitValueString[0],
year: splitValueString[1]
}
}
},
methods: {
updateDate() {
const monthValue = this.$refs.monthPicker.value;
const yearValue = this.$refs.yearPicker.value;
this.$emit('input', `${monthValue}/${yearValue}`);
}
}
};
</script>
The methods
object applies the property updateDate()
to emit the updated month
and year
from an input string. You can now import the StringDatePicker
advanced custom component into another file and operate the v-model
directive to bind and add your values from your month
and year
properties at once.
Conclusion #
The v-model
directive provides extra functionality when implemented in custom Vue.js components. You can also integrate two-way data binding into advanced custom components to manipulate data types into precise formats.
For further reading about Vue.js, check out the Vue.js topic page.