Search code examples
arraysvue.jswatchcomputed-properties

In an array of obects watched with Vue-watch, how to get index of object that was changed?


I have an array of objects, like this:

 myArray: [{
 name: "First",
 price: 10,
 rebate: 5,
 listPrice: 15,
 outcome: 0
 },{
 name: "Second",
 price: 11,
 rebate: 5,
 listPrice: 16,
 outcome: 0
}

I want to recalculate the outcome-value whenever any of the other values in the same object change.

I already have a setup like this, but it looks for changes in any object and then recalculates the whole array. I've managed to set this up by using a combination of computed and watch functions. However they watch the whole array for changes and then recalculate the outcome-value for all objects in the array.

How can I watch for changes and then recalculate only the changed object?

Below is my current functions for recalculating the whole array (watching another property), but what I'm looking for could be completely different.

computed:

myArrayWasChanged() {
return [this.myArray.reduce((a, {vendors}) => a + vendors, 0), this.myArray.filter(item => item.discounted == false).length] 

watch:

myArrayWasChanged: {
handler: function (val, oldVal) {
this.recalculateIsVendor();

Solution

  • Given the outcome is completely dependent on the other properties, it isn't really part of the component's state. Thus, in the component's data you could store the array without the outcome, and then calculate a new version of the array with the outcome as a computed property.

    data: function () {
      return {
        myArrayWithoutOutcome: [
        {
          name: "First",
          price: 10,
          rebate: 5,
          listPrice: 15
        },
        {
          name: "Second",
          price: 11,
          rebate: 5,
          listPrice: 16
        }]
      }
    },
    computed: {
      myArrayWithOutcome: function () {
        return this.myArrayWithoutOutcome.map(x => {
          return {...x, outcome: this.calculateOutcome(x)}
        })
      }
    },
    methods: {
      calculateOutcome(item) {
        // Logic to calculate outcome from item goes here
        return 0
      }
    }