2

I have a vue (version 2.x) file where I have 3 fields - input1 x input2 = result

Now, when I change any one of them, the other two should be updated on the fly. I tried using watch property but that leads to infinite loop because the watchers keep calling each other.

Is there any vue related helper which I am missing here? Any help would be appreciated.

Refer this for example code.

<template>
  <input v-model="input1"></input>
  <input v-model="input2"></input>
  <input v-model="conversionRate"></input>
</template>

<script>
export default {
  data() {
    input1: null,
    input2: null,
    conversionRate: null
  },
  watch: {
    input1() {
      this.input2 = this.input1 * this.conversionRate
    },
    input2() {
      this.input1 = this.input2 * this.conversionRate
    },
    conversionRate() {
      this.input2 = this.input1 * this.conversionRate
    }
  }
}
</script>
6
  • what it is supposed to do with input1 and input2 if we edit result ? Commented Jun 13, 2018 at 11:13
  • I am basically doing a currency conversion. input2 is the conversion rate here. So to answer your question, if you edit the result, keep input2 fixed and change input1. Commented Jun 13, 2018 at 11:15
  • If everything is bound properly and you're using v-model, the fields should update automatically anyway. P.s Show some code. Commented Jun 13, 2018 at 11:20
  • I think you'll have to use @input and :value= instead of v-model and use intermediate values to prevent this effect of infinite loop. (currency1InputValue -> currency1, currency2InputValue -> currency2, etc...) Commented Jun 13, 2018 at 11:28
  • Let me write the basic code and add it in the question itself @webnoob Commented Jun 13, 2018 at 11:31

2 Answers 2

1

Since all three models are dependent on each other it causes an infinite loop.

As per your requirement you can use computed setter.

HTML

<div id="app">
  <input type="number" placeholder="amount" v-model="inputA"> X
  <input type="number" placeholder="rate" v-model="conversionRate"> =
  <input type="number" placeholder="total" v-model="total">
</div>

SCRIPT

new Vue({
  el: "#app",
  data: {
    total: 0,
    conversionRate: 1
  },
  computed: {
    inputA: {
      get() {
        return this.total / this.conversionRate;
      },
      set(newVal) {
        this.total = newVal * this.conversionRate;
      }
    }
  }
});

Here is the working fiddle

Sign up to request clarification or add additional context in comments.

2 Comments

this works just fine. But when I use Math.round, the get(),set() and get() gets called and it does not work as expected. Suppose if I change the total, the get() is called, which changes the inputA value, which calls set(), which in turn changes the total value again. So the value which I type gets changed. Can you help me with this situation?
inputA: { get() { return Math.round(this.total / this.conversionRate); }, set(newVal) { this.total = Math.round(newVal * this.conversionRate); } }
0

Your watcher at input2 is wrong which causes infinite loop (if the calulcation is based on float, you'd better to use Math.round), it should be:

input2: function (newVal) {
   this.input1 = newVal / this.conversionRate // not newVal*this.conversionRate
}

But @Vamsi Krishna should be an better solution.

The demo:

app = new Vue({
  el: "#app",
  data: function () {
    return {
      input1: null,
      input2: null,
      conversionRate: 1
    }
  },
  watch: {
    input1: function (newVal) {
      this.input2 = newVal * this.conversionRate
    },
    input2: function (newVal) {
      this.input1 = newVal / this.conversionRate
    },
    conversionRate: function (newVal) {
      this.input2 = this.input1 * newVal
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
  <input v-model="input1">
  <input v-model="input2">
  <input v-model="conversionRate">
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.