[Vuejs]-Mark a single icon from many – vue.js

2πŸ‘

βœ…

Every object should have it property isMark as below:

UPDATE: you can merge properties to your original data after be fetched:

const myData = [
  { title: "one"},
  { title: "two" },
  { title: "three" },
  { title: "four" },
]

new Vue({
  el: '#app',

  data() {
    return {
      isLoading: true,
      allBooks: []
    }
  },
  
  created() {
    this.fetchAPI()
  },
  
  methods: {
    fetchAPI() {
      setTimeout(() => {
        this.allBooks = myData.map(item => ({...item, isMark: false }))
        this.isLoading = false
      }, 2000)
    },
    
    markAsFavorite(book) {
      book.isMark = !book.isMark
    }
  }
})
.my-icon {  
  cursor: pointer;
  margin-left: 4px;
}

.isActive {
  color: red;
}

.flex {
  display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/js/all.min.js"></script>

<div id="app">
  <span v-if="isLoading">
    loading
    <i class="fas fa-spinner fa-spin"></i>
  </span>
  
  <template v-else>
    <div class="flex" v-for="(book, index) in allBooks" :key="index">
      <div>Title: {{ book.title }}</div>
      <span
        :class="[
          { isActive: book.isMark }, 
          'my-icon'
        ]"
        @click="markAsFavorite(book)"
      >
        <i class="fas fa-heart"></i>
      </span>
    </div>
  </template>
</div>

1πŸ‘

I would separate out each book into its own component. That way it can track its own isMark

Book.vue

<template>
  <div>
    <div>Title: {{ book.title }}</div>
    <i @click="markAsFavorite" :class="{isActive: isMark}" class="fas fa-heart"></i>
  </div>
</template>

<script>
export default {
  name: 'Book',
  props: { book: Object },
  data: () => ({ isMark: false }),
  methods: {
    markAsFavorite () {
      this.isMark = !this.isMark
      this.$emit(this.isMark ? 'marked' : 'unmarked', this.book)
    }
  }
}
</script>

and then in your Books component

<template>
  <v-flex v-for="(book, index) in allBooks" :key="index">
    <Book :book="book" @marked="handleMarked" @unmarked="handleUnmarked" />
  </v-flex>
</template>

<script>
import Book from './Book.vue'

export default {
  name: 'Books',
  components: { Book },
  // and so on
}
</script>
πŸ‘€Phil

Leave a comment