One option is to use the v-model binding with computed properties so you can control the set logic.
new Vue({
el: '#app',
data: {
priceBeforeDiscount: 100,
discount: 50,
priceAfterDiscount: 50,
},
computed: {
priceAfterDiscountInput: {
get() {
return this.priceAfterDiscount;
},
set(val) {
this.priceAfterDiscount = val;
this.discount = this.priceBeforeDiscount - this.priceAfterDiscount;
}
},
discountInput: {
get() {
return this.discount;
},
set(val) {
this.discount = val;
this.priceAfterDiscount = this.priceBeforeDiscount - this.discount;
}
}
},
})
Another possibility is to use watchers on discount and priceAfterDiscount. It doesn't lead to an infinite loop in this case because the values reach an equilibrium and watchers only run if the value changes. I'd be cautious about using co-dependent watchers in general though.
new Vue({
el: '#app',
data: {
priceBeforeDiscount: 100,
discount: 50,
priceAfterDiscount: 50,
},
watch: {
discount() {
this.priceAfterDiscount = this.priceBeforeDiscount - this.discount;
},
priceAfterDiscount() {
this.discount = this.priceBeforeDiscount - this.priceAfterDiscount;
}
},
})
However, I don't really think there's an issue with your solution. If you aren't required to use the v-model directive (e.g. for vee-validate), I'd just convert it to v-bind and do the assignment in the input handler.