Search code examples
vue.jsvuejs2

v-model and child components?


I have a form and bind an input using v-model:

<input type="text" name="name" v-model="form.name">

Now I want to extract the input and make it it's own component, how do you then bind the values of the child component to the parents object form.name?


Solution

  • As stated in the documentation,

    v-model is syntactic sugar for:

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

    To implement the v-model directive for a custom component:

    • specify a value prop for the component
    • make a computed property with a computed setter for the inner value (since you should not modify the value of a prop from within a component)
    • define a get method for the computed property which returns the value prop's value
    • define a set method for the computed property which emits an input event with the updated value whenever the property changes

    Here's a simple example:

    Vue.component('my-input', {
      template: `
        <div>
          My Input:
          <input v-model="inputVal">
        </div>
      `,
      props: ['value'],
      computed: {
        inputVal: {
          get() {
            return this.value;
          },
          set(val) {
            this.$emit('input', val);
          }
        }
      }
    })
    
    new Vue({
      el: '#app',
      data() {
        return { 
          foo: 'bar' 
        }
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
    <div id="app">
      <!-- using v-model... -->
      <my-input v-model="foo"></my-input>
      
      <!-- is the same as this... -->  
      <my-input :value="foo" @input="foo = $event"></my-input>
    
      {{ foo }}
    </div>

    Thanks to @kthornbloom for spotting an issue with the previous implementation.

    Breaking changes in Vue 3

    Per the documentation, there are breaking changes to the v-model implementation in Vue 3:

    • value -> modelValue
    • input -> update:modelValue