Tutorial

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

Updated on October 29, 2020
authorauthor

Joshua Bemenderfer and Natalia Vargas-Caba

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 our products

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!

Become a contributor for community

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

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.