Olga B
Olga B

Reputation: 513

Vue.js: Reactively update a component on a click

I have a component for adding/deleting an item to/from favorites. It works perfectly fine but a user cannot see whether he/she added the item to favorites or not (I show a star icon if the item is favorited and an empty one if not). How can I do this reactively? I want my icon to change its class if the user clicked on it.

Here is my code:

Component:

<template>
 <span :class="isFavorite
            ? 'mdi mdi-star favorite'
            : 'mdi mdi-star-outline'"
    class="favorite-item-icon"
    @click="isFavorite ? deleteFromFavoriteItems(itemId) : addToFavoriteItems(itemId)">
 </span>
</template>

<script>
 export default {
  import { mapGetters, mapActions } from 'vuex';

  props: ['itemId', 'isFavorite'],
  methods: {
    ...mapActions(['addToFavoriteItems', 'deleteFromFavoriteItems']),
  },
};
</script>

The component in v-for list of a parent component:

...
 <favorite-label :itemId="item.id" :isFavorite="item.is_favourite" />
...

In my store:

addToFavoriteItems({ commit }, itemId) {
  http
    .post(`${config.api}api/v1/items/favourite-save`, {
      item_id: itemId,
    });
deleteFromFavoriteItems({ commit }, itemId) {
  http
    .post(`${config.api}api/v1/items/favourite-delete`, {
      item_id: itemId,
    });

Upvotes: 0

Views: 77

Answers (1)

Ohgodwhy
Ohgodwhy

Reputation: 50798

You would need to assign the item from the server (after update) to the store, something like:

$post(..., { item_id: itemId }).then(function(response) {
  this.$store.commit('items/SET_ITEM', response.data)
})

Where the items/SET_ITEM mutation loops the items in the current array and updates the item if the id matches.

let itemToUpdate = this.items.forEach(function(i) {
  if (i.id === item.id) {
    i = item
  }
})

Then it should correctly mutate the store dispatching the prop update and causing the view to re-render with the new isFavorite calculation in place.

Alternatively, if the itemId that you're passing can be used, there's no reason for the server to change anything, just pass it along instead, like:

$post(..., { item_id: itemId }).then(function() {
  this.$store.commit('items/UPDATE_FAVORITE', { item: itemId })
})

And now you could just add a mutation that toggles the favorite, basically:

this.items.forEach(function(i) {
  if (i.id === item) {
      i.is_favorite = !i.is_favorite
  }
})

Upvotes: 1

Related Questions