drake035
drake035

Reputation: 2877

Computed property doesn't update upon changing data variable

I have a data variable named monRaw that is a Moment object representing the first day of current week:

...
data() {
  return {
    monRaw: moment().startOf('isoWeek')
  }
},
...

Then I have a computed property named weekTitle that displays it along with some text (it does more than that in my project, but I simplified it here):

...
computed: {
  weekTitle: function() {
    alert('updating computed property...');
    return `Current week starting on ${this.monRaw.format('DD')}`;
  }
},
...

Finally, a method named viewNextWeek() changes my data variable to the following week's first day:

...
methods: {
  viewNextWeek: function() {
    this.monRaw = this.monRaw.add(1, 'weeks');
  },
...

In my template, I display my computed property along with a button triggering my method:

{{ weekTitle }}
<button @click="viewNextWeek">Next Week</button>

For some reason though, my computed property does NOT get updated when I change the data variable it's based on.

It doesn't even try to: my alert() gets triggered on page load only, not any more after that when clicking the button.

What's wrong here?

Upvotes: 2

Views: 1699

Answers (1)

Roy J
Roy J

Reputation: 43881

Moment.add mutates the moment variable, so you are just assigning the same object back to itself, which results in no change.

Per the docs:

If you want to create a copy and manipulate it, you should use moment#clone before manipulating the moment.

new Vue({
  el: '#app',
  data: {
    monRaw: moment().startOf('isoWeek')
  },
  computed: {
    weekTitle: function() {
      alert('updating computed property...');
      return `Current week starting on ${this.monRaw.format('DD')}`;
    }
  },
  methods: {
    viewNextWeek: function() {
      const newValue = this.monRaw.clone().add(1, 'weeks');

      this.monRaw = newValue;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  {{ weekTitle }}
  <button @click="viewNextWeek">Next Week</button>
</div>

Upvotes: 4

Related Questions