Tutorial

How To Add Two-Way Data Binding to Custom Components in Vue.js

Updated on October 28, 2020
Default avatar

By Joshua Bemenderfer

How To Add Two-Way Data Binding to Custom Components in Vue.js

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.

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.

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.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Joshua Bemenderfer

author



Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
3 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Thank you for this article! But - I do not understand why the v-model on the date-picker component is called “date-picker”? Wouldn’t that require and equally named attribute on the parent’s data object? But I only see it return a “date” object…

Hi sir,

I am using Vuelidate validation for my form, is there any tutorial to add it into a nested object which uses in a custom component?

This is one way. *Child only emits data to parent

How can the parent update the child data?

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel