Vue filtering list

Add/remove items from an array Filter array

by Compay

HTML

<div id="app">
  <h2>Filters:</h2>
  <ol>
    <li v-for="filter in possibleFilters" :key="filter">
      <label>
        <input type="checkbox"
          @change="toggleFilter(filter)"
          :checked="filters.includes(filter)">
        <span>{{ filter }}</span>
      </label>
    </li>
  </ol>
  
  <hr>
  
  <h2>Products:</h2>
  <ol>
    <li v-for="product in matchedAndSortedProducts" :key="product.title">{{ product.title }}</li>
  </ol>

</div>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

hr {
  margin: 24px 0;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

del {
  color: rgba(0, 0, 0, 0.3);
}

Vue

new Vue({
  el: "#app",
  data: {
    filters: [],
    products: [
      { title: "3 Bedroom Apartment", topic: "Houses" },
      { title: "Renault Scenic", topic: "Cars" },
      { title: "Mazda 6", topic: "Cars" },
      { title: "Childish Tycoon", topic: "Boats" },
      { title: "RMS Lusitania", topic: "Boats" },
      { title: "HMS Beagle", topic: "Boats" }
    ]
  },
  methods: {
    toggleFilter: function (newFilter) {
      this.filters = !this.filters.includes(newFilter) 
        ? [...this.filters, newFilter] 
        : this.filters.filter(filter => filter !== newFilter)
    }
  },
  computed: {
    possibleFilters() {
      return this.products
        .map(({ topic }) => topic)
        .filter((value, index, self) => self.indexOf(value) === index);
    },
    matchedProducts() {
      return this.filters.length 
        ? this.products.filter(product => this.filters.some(filter => product.topic.match(filter))) 
        : this.products
    },
    matchedAndSortedProducts() {
      return this.matchedProducts.sort(/* something here */);
    }
  }
})