// Tutorial //

How To Add v-model Support to Custom Vue.js Components

Published on December 12, 2019 · Updated on October 28, 2020
Default avatar
By Samuel Oloruntoba
Developer and author at DigitalOcean.
How To Add v-model Support to Custom Vue.js Components

Introduction

The v-model directive is one of the few directives that comes bundled with Vue.js. This directive allows for two-way data binding between our data and views.

With two-way data binding, when we update our data via input fields or other controls, we can modify the DOM (Document Object Model) without having to do DOM work.

In this article, you’ll explore how this directive works and use it for your own components.

Understanding How v-model Works Internally

From our knowledge of HTML, we know that input, select, and textarea are the main ways we feed data to our application.

For v-model to work, it expects the element or component in question to receive a prop (default is value) and also emit an event (default is input).

Depending on the element, Vue decides how to listen and handle the data. For input elements, you might use v-model like this:

<input v-model="email" />

v-model translates to this:

<input :value="email" @input="e => email = e.target.value" />

Vue uses this expansion to handle textarea, select, and some other input types.

For radio buttons and checkboxes, Vue uses their checked prop and listens for their change event.

For elements like select tags and checkboxes that can accept multiple values, Vue will automatically return an array of selected values.

Adding v-model to Custom Components

To let our component support v-model two-way binding, the component needs to accept a value prop and emit an input event.

Let’s create a sample component called basic-input. We’ll use Vue’s single file component:

basic-input.vue
<template>
  <input @input="handleInput" />
</template>

<script>
export default {
  prop: ['value'],
  data () {
    return {
      content: this.value
    }
  },
  methods: {
    handleInput (e) {
      this.$emit('input', this.content)
    }
  }
}
</script>

To support v-model, the component accepts a value prop and emits an input event.

Use the component like this:

<basic-input v-model="email" />

With that, the custom component supports v-model two-way binding.

Customizing v-model prop and event

Let’s take it a step further. We might not want to use the default event and prop needed to add v-model support to our components. Thankfully, Vue allows us to customize it.

To customize the event and ``prop, we add a model property to our component and define the new values like this:

basic-input.vue
// ...

export default {
  prop: ['hidden'],
  model: {
      prop: 'hidden',
      event: 'blur'
  }
  methods: {
      handleInput (value) {
          this.$emit('blur', value)
      }
  }
}

// ...

This time, when you use the component like this:

<basic-input v-model="email" />

Vue will automatically convert it into:

<basic-input :hidden="email" @blur="e => email = e.target.value" />

With this in place, you can avoid conflicts when defining your component’s props and events.

Using v-model on contenteditable

A content editable element is a div or similar element that can be configured to work as an input.

We define content editable elements by adding the contenteditable attribute to the element:

<div class="editor" contenteditable="contenteditable"></div>

You’ll use content editable elements for WYSIWYG editors as they are easier to work with and are supported by a large amount of browsers.

v-model will work on content editable elements, but you need to explicitly use the content of the element, or the content will not be emitted.

To emit the content, you need to grab the innerText or innerHTML of the div. So, our updateInput method needs to look like this:

updateInput () {
  this.$emit('input', this.$el.innerText)
}

You can also use the content of a ref instead of the root element’s content.

With this in place, v-model will work for content editable elements. You could also update this.content in the updateInput method.

Conclusion

Now that you have seen how to use v-model with custom Vue components, you can go build or refactor your components that require the use of v-model.

For further reading, consult the official documentation for v-model or check out the Vue.js topic page for more exercises or projects.


Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
Developer and author at DigitalOcean.

Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
1 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!

isn’t it props instead of prop in the line: “prop: [‘value’],”