0

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,
    });

1 Answer 1

1

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
  }
})
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much for your suggested solution. Unfortunately, it is still working as it did before. My icon doesn't change itself reactively, only after refresh. Is it possible to add some kind of a watcher?
Okay, I fixed this problem and now my icon updates itself reactively. However, this happens quite slow (approx. 2 sec). Is this any way to toggle icons faster? I think it is toggled as soon as my request gets the response and either add or remove item from favorites. But for UX this behaviour is a little bit slow... :(
@OlgaB You can perform the commit BEFORE the post request and use .catch(error) to roll it back if there's a problem

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.