Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

v-model and child components?

Tags:

vue.js

vuejs2

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?

like image 218
panthro Avatar asked Nov 15 '17 15:11

panthro


People also ask

How do you use V-model components?

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. To support v-model , the component accepts a value prop and emits an input event. With that, the custom component supports v-model two-way binding.

What does V-model do?

The V-model is a graphical representation of a systems development lifecycle. It is used to produce rigorous development lifecycle models and project management models.

What is parent and child component in Vue?

Parent To Child Communication In Vue. To move data from a parent component to a child component in Vue we use something called props. ReactJS also uses a similar convention for sharing data. Props is short for “properties” and is referring to properties set from outside, such as from the parent component.

What does V-model lazy do?

lazy. By default, v-model syncs with the state of the Vue instance (data properties) on every input event - which means every single time the value of our input changes. The . lazy modifier changes our v-model so it only syncs after change events.


2 Answers

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
like image 119
thanksd Avatar answered Oct 12 '22 11:10

thanksd


Specify a :value prop and an @input event in the child component, then you can use v-model syntax in the parent component.

Vue 2

MyInput.vue

<template>   <input      :value="value"      @input="$emit('input', $event.target.value)" /> </template>  <script> export default {   props: ['value'] }; </script> 

Screen.vue

<template>   <my-input v-model="name" /> </template>  <script> import MyInput from './MyInput.vue';  export default {   components: { MyInput },    data: () => ({     name: ''   }) }; </script> 

Vue 3

MyInput.vue

<template>   <input      :value="modelValue"      @input="$emit('update:modelValue', $event.target.value)" /> </template>  <script> export default {   props: ['modelValue'] }; </script> 

Screen.vue

<template>   <my-input v-model="name" /> </template>  <script> import MyInput from './MyInput.vue';  export default {   components: { MyInput },    data: () => ({     name: ''   }) }; </script> 
like image 22
Cameron Wilby Avatar answered Oct 12 '22 11:10

Cameron Wilby