SRR
SRR

Reputation: 1748

Update one field when the other changes - Vue

I'm trying to essentially create a two-way calculator and I've chosen to use inches to millimeters as an example.

See the sandbox here: https://q8y4s.csb.app/

<template>
  <div>
    <input type="number" v-model="inches" placeholder="Inches" />
    <br />
    <input type="number" v-model="mm" placeholder="Millimeters" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      inches: "",
      mm: "",
    };
  },
  watch: {
    inches: function (newVal) {
      this.mm = newVal * 25.4;
    },
    mm: function (newVal) {
      this.inches = newVal / 25.4;
    },
  },
};
</script>

The issue is going from millimeters to inches. I'm not entirely sure what's happening but it seems like a feedback loop of some sort. I know I can use computed to achieve this particular functionality but I'd prefer to use watchers since there is more logic to the 'watched' fields in my project.

This tutorial uses meters to kilometers and accomplishes the same thing but I'm uncertain why millimeters to inches creates the 'feedback loop' effect

Upvotes: 2

Views: 1762

Answers (2)

Derick
Derick

Reputation: 1

I was searching this for long time now. I am new to vue but the following solution worker for me it is in vue3

<template>
    <input type="number" @input = "changetag('1')" v-model.number="state.unit1" placeholder="-">
    <input type="number" @input = "changetag('2')" v-model.number="state.unit2" placeholder="-">
    <input type="number" @input = "changetag('3')" v-model.number="state.unit3" placeholder="-">
</template>

<script>
import { reactive } from 'vue';

export default {
  setup() {
    const state = reactive({
      tag: '',
      unit1: null,
      unit2: null,
      unit3: null, 
    });

    function changetag(value){
      state.tag = value;
      if (value =='2')
        state.unit1 = state.unit2/2
      if (value =='3')
        state.unit1 = state.unit3/3
      updatevalue(value)
    }

    function updatevalue(value){
      if (value!='2')
        state.unit2 = state.unit1*2
      if (value!='3')
        state.unit3 = state.unit1*3
    }

    return{
      state,
      changetag,
      updatevalue,
    }
  }
}
</script>

feild2 = 2 times field1 & field3 = 3 times field

Upvotes: 0

Lanny Bose
Lanny Bose

Reputation: 1857

What you could do is create a safety valve to prevent the recursion. Something like:

export default {
  data() {
    return {
      isChangingMm: false,
      isChangingInches: false,
      // others
    }
  },
  watch: {
    inches: function (newVal) {
      if (!this.isChangingMm) {
        this.isChangingInches = true
        this.mm = newVal * 25.4
        this.isChangingInches = false
      }
    },
    mm: function (newVal) {
      if (!this.isChangingInches) {
        this.isChangingMm = true
        this.inches = newVal / 25.4
        this.isChangingMm = false
      }
    }
  },
}

Upvotes: 2

Related Questions