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

Updated on October 28, 2020

Samuel Oloruntoba and Bradley Kouchi

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


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:

  <input @input="handleInput" />

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

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:

// ...

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.


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.

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
Samuel Oloruntoba


Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?

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!

WARNING: out of date information. Please check the doumentation at


For using v-model on Components with the Composition API see: https://vuejs.org/guide/components/events.html#usage-with-v-model

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

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!

Featured on Community

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