Home > Software design >  Binding child input :value to the parent prop
Binding child input :value to the parent prop

Time:12-24

I try to bind child input value to the parent value. I pass value searchText from a Parent component to a Child component as prop :valueProp. There I assign it to property value: this.valueProp and bind input:

<input type="text" :value="value" @input="$emit('changeInput', $event.target.value)" />

The problem is that input doesn't work with such setup, nothing displays in input, but parent searchText and valueProp in child update only with the last typed letter; value in child doesn't update at all, though it is set to equal to searchText.

If I remove :value="value" in input, all will work fine, but value in child doesn't get updated along with parent's searchText.

I know that in such cases it's better to use v-model, but I want to figure out the reason behind such behavior in that case.

I can't understand why it works in such way and value in child component doesn't update with parent's searchText. Can you please explain why it behaves in that way?

Link to Sanbox: Sandbox

Parent:

<template>
  <div>
      <Child :valueProp="searchText" @changeInput="changeInput" />
      <p>parent {{ searchText }}</p>
  </div>
</template>

<script>
import Child from "./Child.vue";

export default {
  name: "Parent",
  components: { Child },
  data() {
    return {
      searchText: "",
    };
  },
  methods: {
    changeInput(data) {
      console.log(data);
      this.searchText = data;
    },
  },
};
</script>

Child:

<template>
  <div>
    <input type="text" :value="value" @input="$emit('changeInput', $event.target.value)" />
    <p>value: {{ value }}</p>
    <p>child: {{ valueProp }}</p>
  </div>
</template>

<script>
export default {
  emits: ["changeInput"],
  data() {
    return {
      value: this.valueProp,
    };
  },
  props: {
    valueProp: {
      type: String,
      required: true,
    },
  },
};
</script>

CodePudding user response:

You set the value in your Child component only once by instantiating.

In the data() you set the initial value of your data properties:

data() {
    return {
      value: this.valueProp,
    };
},

Since you don't use v-model, the value will never be updated.

You have the following options to fix it:

  1. The best one is to use v-model with value in the Child.vue

 <input
      type="text"
      v-model="value"
  1. update value using watcher

 watch: {
    valueProp(newValue) {
        this.value = newValue;
    }
  },
  1. use a computed property for value instead of data property

computed: {
    value() {return this.valueProp;}
} 

Respect for creating the sandbox!

CodePudding user response:

You are overwriting the local value every time the value changes

data() {
  return {
    value: this.valueProp, // Don't do this
  };
},

Bind directly to the prop:

<input ... :value="valueProp" ... />
  • Related