VueJS. v-model in custom component

v-model uses the @input event by default, so if you want to use v-model on a custom component you need to emit the input event to the parent. So, in your component, you simply do:

<input class="product_name form-control" @input="$emit('input', $event.target.value)" />

Now in your parent you can do:

<products-list v-model="product.name"></products-list>

You can see the full example on this JSFiddle: https://jsfiddle.net/7s2ugt11/


There are breaking changes for Vue 3.x:

BREAKING: When used on custom components, v-model prop and event default names are changed:
prop: value -> modelValue;
event: input -> update:modelValue;

https://v3.vuejs.org/guide/migration/v-model.html

So your child component would be:

<template>
  <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>

<script>
export default {
  name: "ProductsList",
  props: ['modelValue']
}
</script>

And in the parent component you would not change anything:

<products-list v-model="product.name"></products-list>

Using v-model in custom components sometimes will lead us to some conflicts.

Or we just want to use the value for different purpose.

That's why vue introduced model. Please take a look to it.

<!-- Parent Component -->
<div id="app">
  <my-checkbox v-model="checked" value="unchanged"></my-checkbox>{{checked}}
</div>

<!-- Child Component -->
<template id="my_checkbox">
  <div>
   My value is {{value}} <br>
   <input type="checkbox" :value="value" @change="$emit('change', !checked)">  
  </div>
</template>

And the script:

Vue.component('my-checkbox', {
    template: '#my_checkbox',
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    // this allows using the `value` prop for a different purpose
    value: String,
    // use `checked` as the prop which take the place of `value`
    checked: {
      type: Boolean,
      default: false
    }
  },
})

new Vue({
  el: "#app",
  data: {
        checked: null
  },    
})

See it in action

Tags:

Vue.Js