Search code examples
vue.jsvue-component

Vue: How do you bind a value to an input through a wrapper component?


I know you can use v-model to bind a value to an input in the same component. How do you create a wrapper component for an input and bind a value to it?

Login.vue

<template>
  <div id="Login">
    <Input v-bind:value="email"/>    
    <Input v-bind:value="password"/>

  </div>
</template>
<script>
  import Input from './Input.vue'
  import Button from './Button'

  export default {
    name: 'Login',
    components: {
        Input,
        Button,
    },
    data: () => ({
        email:'test',
        password:'test',
    }),
    methods: {
        login: () => { debugger; }, //this.email and this.password are still set to test
    }
  }
</script>

Input.vue

<template>
  <div class="input>
   <input v-model="value"/>
  </div>
</template>
<script>
  export default {
    name: 'Input',
    props: {
        value: String,
    },
  }
</script>

Current set up results in

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"

Is the only way to do this by emitting an event?


Solution

  • The best way is use v-model for wrapper and on/emit for input

    <div id="Login">
        <Input v-model="email"/>    
        <Input v-model="password"/>    
    </div>
    

    ...

    <div class="input>       
       <input        
         v-bind:value="value"
         v-on:input="$emit('input', $event.target.value)"
       >
    </div>