[Vuejs]-Why won't v-model of a subcomponent reflow from an emit changed to the parent?

3👍

There are two ways to achieve this.

Option 1 – Bind v-model to a local variable, but watch the prop value for changes and update local variable on prop change:

<template>
  <v-text-field v-model="localValue" @blur="compute" @keydown.enter="compute" />
</template>

<script>
import { create, all } from "mathjs";
const math = create(all);

export default {
  name: "NumericTextField",
  props: ["value"],
  data() {
    return {
      localValue: this.value
    };
  },
  watch: {
    value: function(newVal) {
      this.localValue = newVal;
    }
  },
  methods: {
    compute() {
      try {
        const result = math.evaluate(this.localValue);
        this.$emit("input", result);
      } catch (e) {
        console.log(e);
      }
    }
  }
};
</script>

Option 2 – use value as input value, but track v-text-field changes in a separate local variable. This way you don’t need to use watch.

<template>
  <v-text-field :value="value" @blur="compute" @keydown.enter="compute" @input="onInput" />
</template>

<script>
import { create, all } from "mathjs";
const math = create(all);

export default {
  name: "NumericTextField",
  props: ["value"],
  data() {
    return {
      localValue: this.value
    };
  },
  methods: {
    compute() {
      try {
        const result = math.evaluate(this.localValue);
        this.$emit("input", result);
      } catch (e) {
        console.log(e);
      }
    },
    onInput(val) {
      this.localValue = val;
    }
  }
};
</script>
👤Beyers

0👍

It’s because by using v-model, you change the localValue, which is not equal to this.value anymore. You should try to remove localValue completely, and use this.value instead.

<v-text-field
    v-model="value"
    @blur="compute"
    @keydown.enter="compute"
/>
compute () {
   try {
       const result = math.evaluate(this.value)
          this.$emit("input", result)
            } catch (e) {
                console.log(e)
            }
        },


👤Bulent

0👍

Try to bind the text field directly to value prop using value attribute and remove the localValue

<template>
  <v-text-field
    :value="value"
    @blur="compute"
    @keydown.enter="compute"
  />
</template>

<script>
import { create, all } from 'mathjs'
const math = create(all)

export default {
    name: "NumericTextField",
    props: ["value"],
    methods: {
        compute () {
            try {
                const result = math.evaluate(this.value)
                this.$emit("input", result)
            } catch (e) {
                console.log(e)
            }
        },
    },
}
</script>

if the above example doesn’t work try out the following

<template>
  <v-text-field v-model="localValue" @blur="compute" @keydown.enter="compute"
 
  />
</template>

<script>
import { create, all } from "mathjs";
const math = create(all);

export default {
  name: "NumericTextField",
  props: ["value"],
  data() {
    return { localValue: "" };
  },
  watch: {
    value(v) {
      this.localValue = v;
    },
  },
  methods: {
    compute() {
 
      try {
        const result = math.evaluate(this.localValue);
        this.$emit("input", result);
      } catch (e) {
        console.log(e);
      }
    },
  },
};
</script>

LIVE DEMO

Leave a comment