Skip to content
Search

V-model

lastmod 2021-07-23created 2020-10-1514 edits

Form input binding in Vue.js.

Simply put, think of it as v-model = v-bind:value + v-on:input.

Basic usage

You can use the v-model directive to create two-way data bindings on form input and textarea elements. It automatically picks the correct way to update the element based on the input type. Although a bit odd, v-model is essentially syntax sugar for updating data on user input events, and it requires special care in some cases.

Creating form input components using custom events

Custom events can also be used to create custom inputs that work with v-model. Remember:

<input v-model="something">

The statement above is the same as the following.

<input
  v-bind:value="something"
  v-on:input="something = $event.target.value">

When used with a component, it simplifies to the following.

<custom-input
  :value="something"
  @input="value => { something = value }">
</custom-input>

So for a component to work with v-model, it should (this can be configured in version 2.2.0 and later):

  • Accept a value prop.
  • Emit an input event with the new value.

INFORMATION

In other words, v-model is a combination of v-bind:value and v-on:input

Let's look at a very simple currency input in use.

<currency-input v-model="price"></currency-input>
Vue.component('currency-input', {
  template: '\
    <span>\
      $\
      <input\
        ref="input"\
        v-bind:value="value"\
        v-on:input="updateValue($event.target.value)">\
    </span>\
  ',
  props: ['value'],
  methods: {
    // 값을 직접 업데이트하는 대신 이 메소드를 사용하여
    // 입력 값에 대한 서식을 지정하고 배치 할 수 있습니다
    updateValue: function (value) {
      var formattedValue = value
        // 공백을 제거합니다.
        .trim()
        // 소수 자릿수 2자리로 줄입니다
        .slice(
          0,
          value.indexOf('.') === -1
            ? value.length
            : value.indexOf('.') + 3
        )
      // 값이 아직 정규화 되지 않은 경우
      // 이를 수동으로 재정의하여 조건을 충족시킵니다.
      if (formattedValue !== value) {
        this.$refs.input.value = formattedValue
      }
      // 입력 이벤트를 통해 숫자 값을 내보냅니다.
      this.$emit('input', Number(formattedValue))
    }
  }
})

The implementation above is pretty naive. For example, users can sometimes enter multiple periods and letters. That's why you may want to use a more robust currency filter.

WARNING

With Korean (Hangul) input, v-model works properly only after a character is fully composed. If you want incomplete characters to be applied as well, don't use v-model; implement v-bind and v-on separately instead.

Customizing v-model on components

INFORMATION

Added in version 2.2.0

By default, v-model on a component uses value as the prop and input as the event, but some input types such as checkboxes and radio buttons may want to use the value attribute for a different purpose. Using the model option can avoid the conflict in such cases:

Vue.component('my-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    // 다른 목적을 위해 `value` prop를 사용할 수 있습니다.
    checked: Boolean,
    value: String
  },
  // ...
})
<my-checkbox v-model="foo" value="some value"></my-checkbox>

The above is the same as:

<my-checkbox
  :checked="foo"
  @change="val => { foo = val }"
  value="some value">
</my-checkbox>

WARNING

You must explicitly declare the checked prop.

.lazy

.number

.trim

.sync

Simple Example

<input v-model="message" placeholder="여기를 수정해보세요">
<p>메시지: {{ message }}</p>

Custom Component

How to use v-model on a custom component in vue.

App.vue

<template>
  <div class="wrapper">
    <date-picker v-model="date"></date-picker>
    <p>
      Month: {{date.month}}
      Year: {{date.year}}
    </p>
  </div>
</template>

<script>
import DatePicker from './DatePicker.vue';

export default {
  components: {
    DatePicker
  },

  data() {
    return {
      date: {
        month: 1,
        year: 2017
      }
    }
  }
})
</script>

DatePicker.vue

<template>
  <div class="date-picker">
    Month: <input type="number" ref="monthPicker" :value="value.month" @input="updateDate()"/>
    Year: <input type="number" ref="yearPicker" :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>

See also

Favorite site

author Zer0 sitemap