Search code examples
vue.jsvuejs2vuex

Using conditional class with store getters: not updating class


I have a div with a conditional class that works well when the app is loaded, but it's not updated when the store data change.

The code in my vue component looks like this

<span class="week-day" 
    v-bind:class="{ complete: isDayComplete(day) }" 
    v-for="day in daysInWeek" 
    v-bind:data-day="day"
>&nbsp;</span>

And I have ...mapGetters(['isDayComplete']) in my computed object.

The getter looks like this

isDayComplete(state) {
  return (day) => {
    console.log(`called isDayComplete(${day})`)
    const formattedDay = moment(day, 'DD/MM/YYYY').format('YYYY-MM-DD');
    if (state.daysData[formattedDay]) {
      if (state.daysData[formattedDay].meals.length > 0) {
        console.log(`day ${day} is complete`);
        return true;
      } else {
        console.log(`day ${day} is NOT complete`);
        return false;
      }
    } else {
      console.log(`no data for day ${day}`);
      return false;
    }      
  }
},

I update my meals data in a mutation

updateMeals(state, meals) {
  _.forEach(meals, (meal) => {
    state.daysData[meal.day].meals.push(meal);
  });
}

And I have an action that commits that mutation

loadMeals({ state, commit }) {
  return new Promise((resolve, reject) => {
    get.meals.from.api()
      .then((response) => {
        commit('initDaysData');
        commit('updateMeals', response.data.data);
        return resolve();
      })
    .catch(reject);
  });
}

So whenever I call loadMeals the class is not updated if one day changes its status (complete/not-complete). If I reload the page, the class is set correctly.

What am I doing wrong? Thanks!


Solution

  • It's a common reactivity problem. You can make deep copy (use JSON.parse(JSON.stringify())) to make data reactive:

    updateMeals(state, meals) {
      _.forEach(meals, (meal) => {
        state.daysData[meal.day].meals.push(meal);
      });
      state.daysData = JSON.parse(JSON.stringify(state.daysData))
    }