[Vuejs]-Managing VueJs Watchers Dynamically

0👍

here is a solution using computed values

each parameter (net, margin, sell) are abstracted through a computed value. the getter returns the this.item value, the setter first updates this.item value and then updates the related values.

This is a similar issue as a color picker, you can see a more complex version of this problem here http://jsfiddle.net/Phunky/2enc99r1/

Vue.component('pricing', {
	template: '#pricing-row',
  props: ['item'],
  computed: {
  	net:{
    	get () {
      	return Number(this.item.net)
      },
      set (net) {
      	this.item.net = Number(net)
        this.setSellPrice()
      }
    },
  	margin:{
    	get () {
      	return this.item.margin
      },
      set (margin) {
      	this.item.margin = Number(margin)
        this.setSellPrice()
      }
    },
  	sell:{
    	get () {
      	return this.item.sell
      },
      set (sell) {
      	this.item.sell = Number(sell)
      	this.setMargin()
      }
    }
  },
  methods: {
    
    setSellPrice() {
      let price = (100 / (100 - this.margin)) * this.net
      this.item.sell = price.toFixed(2)
    },
    
    setMargin() {
      let profit = (this.sell - this.net)
      let price = (100 * profit) / this.sell
      this.item.margin = Number(price.toFixed(2))
    }
  }
  
})

new Vue({
  el: '#vue',
  data: {
  	prices: [
    	{ 
      	id: 1,
        net: 5,
        margin: 10,
        sell: 5.56
      },
    	{ 
      	id: 2,
        net: 7,
        margin: 10,
        sell: 7.78
      },      
    ]
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.5/vue.min.js"></script>
<script type="text/x-template" id="pricing-row">
  <tr>
  	<td><input v-model="net" /></td>
    <td><input v-model="margin"  /></td>
    <td><input v-model="sell"  /></td>
  </tr>	
</script>


<div id="vue">
  <table>
    <tr>
      <th>Net</th>
      <th>Margin</th>
      <th>Price</th>
    </tr>
    <tr is="pricing" v-for="(price, index) in prices" :item="price" :key="price.id"></tr>
  </table>
</div>

Leave a comment