Search code examples
vue.jsvuejs2watchcomputed-properties

Access component instance from vue watcher


I'm working on a project, similar as a bill manager, so I want that the subtotal get recalculated every time that quantity or unit value change, I have tried and searched to accomplish this using watcher or computed properties, but I don't find the right approach, cause I need to access the whole scope of the element when another change, like this.

Model structure:

  • detail
  • quantity
  • unit value
  • subtotal (should be a computed or updated)

So I think I should be able of doing something like this:

    Vue.component('item', {
    template: '#item',
    props: {
      item: Object,
    },
    computed:{
        total: function(){ 
            return this.quantity*this.unit_value;
         }
    },
    watch:{
      'item.quantity':()=>{
        this.subtotal = this.quantity*this.unit_value;
      }
    }
  });

I have several components being read from a list

I merged the approach using watcher and computed in the same code to make it shorter.

The problem is that I haven't found a way to access the hole element from inside itself, anyone could pls explain the right way? thanks


Solution

  • You shouldn't use arrows functions there, use method declarations.

    If you want to watch for a property of the item object, you'll have to watch for the item object itself, and additionally use the deep: true flag of the watcher.

    Final detail, you are using several properties that are not declared in your data. Declare them, otherwise they will not be reactive, that is, the computed will not recalculate when they change.

    See code:

    Vue.component('item', {
      template: '#item',
      props: {
        item: Object,
      },
      data() {
        return {
          subtotal: null,         // added data properties
          quantity: null,
          unit_value: null
        }
      },
      computed: {
        total: function() {
          return this.quantity * this.unit_value;
        }
      },
      watch: {
        item: {                          // watching for item now
          deep: true,                    // using deep: true
          handler() {                    // and NOT using arrow functions
            this.subtotal = this.quantity * this.unit_value;
          }
        }
      }
    });