1

I have a selection of checkbox groups (hotel type and locations) and I want to filter the results based on what has been selected. How can I add my selectedLocations and types to the filteredHotels() method and get a filtered result. Sydney Hotels, Sydney Backpackers, Sydney or Melbourne hotels or all Hotels if only hotels is selected.

HTML

  <div>
    <div class="row pt-5">
        <div class="col">
            <h5>Locations</h5>
            <label v-for="(value, key) in locations">
                {{value}}
                <input type="checkbox" :value="value" v-model="selectedLocations">
            </label>
            {{selectedLocations}}
        </div>
    </div>

    <div class="row pt-5">
        <div class="col">
            <h5>Type</h5>
            <label v-for="(value, key) in types">
                {{value}}
                <input type="checkbox" :value="value" v-model="selectedTypes">
            </label>
            {{selectedTypes}}
        </div>
    </div>


    <transition-group class="row" style="margin-top:30px;" name="list" tag="div" mode="out-in">
        <div class="col-sm-4 pb-3 list-item" v-for="(hotel, index) in filteredHotels" :key="index">
            <div class="sau-card">
                <i class="fal fa-server fa-3x"></i>
                <h2>{{hotel.name}}</h2>
                <p>{{hotel.type}}</p>
                <p>{{hotel.location}}</p>

            </div>
        </div>
    </transition-group>
</div>

Data

data() {
        return {
            locations:['Sydney','Melbourne'],
            types:['backpackers','hotel','resort'],
            selectedLocations:[],
            selectedTypes:[],
            hotels:[
                {name:'a Hotel',location:'Sydney', type:'backpackers'},
                {name:'b Hotel',location:'Sydney', type:'hotel'},
                {name:'c Hotel',location:'Sydney', type:'resort'},
                {name:'d Hotel',location:'Melbourne',type:'hotel'},
                {name:'e Hotel',location:'Melbourne', type:'resort'},
                {name:'f Hotel',location:'Melbourne', type:'hotel'},

            ]
        }
    },

Computed

computed:{
    filteredHotels(){
        if(this.selectedLocations.length){
            return this.hotels.filter(j => this.selectedLocations.includes(j.location))
        }
        else if(this.selectedTypes.length){
            return this.hotels.filter(j => this.selectedTypes.includes(j.type))
        }
        else{
            return this.hotels;
        }
    }
}

Fiddle

2 Answers 2

1

Pass your data via binding this or using ()=>, e.g:

filteredHotels(){
   return this.hotels.filter(function (el) {
     return this.selectedLocations.includes(el.location) 
     || this.selectedTypes.includes(el.type)
   }.bind(this));
}

Fiddle

Sign up to request clarification or add additional context in comments.

Comments

0

Here is a working example:

I've updated the condition under computed property as below: Include only location which is being selected. Instead of just returning the current selected location.

computed:{
        filteredHotels(){
        console.log(this.selectedLocations);
        if(!this.selectedLocations.length) {
            return this.hotels;
          } else {
          return this.hotels.filter(j => this.selectedLocations.includes(j.location))
          }
        }
    }

new Vue({
  el: "#app",
  data: {
    locations: ['Sydney', 'Melbourne'],
    types: ['backpackers', 'hotel', 'resort'],
    selectedLocations: [],
    selectedTypes: [],
    filtersAppied: [],
    hotels: [{
        name: 'a Hotel',
        location: 'Sydney',
        type: 'backpackers'
      },
      {
        name: 'b Hotel',
        location: 'Sydney',
        type: 'hotel'
      },
      {
        name: 'c Hotel',
        location: 'Sydney',
        type: 'resort'
      },
      {
        name: 'd Hotel',
        location: 'Melbourne',
        type: 'hotel'
      },
      {
        name: 'e Hotel',
        location: 'Melbourne',
        type: 'resort'
      },
      {
        name: 'f Hotel',
        location: 'Melbourne',
        type: 'hotel'
      },

    ]
  },
  methods: {
    setActive(element) {
      if (this.filtersAppied.indexOf(element) > -1) {
        this.filtersAppied.pop(element)
      } else {
        this.filtersAppied.push(element)
      }
    },
    isActive: function (menuItem) {
      return this.filtersAppied.indexOf(menuItem) > -1
    },
  },
  computed: {
    filterApplied: function() {
      if (this.filtersAppied.indexOf(element) > -1) {
        this.filtersAppied.pop(element)
      } else {
        this.filtersAppied.push(element)
      }
    },
    filteredHotels: function() {
      return this.hotels.filter(hotel => {
        return this.filtersAppied.every(applyFilter => {
          if (hotel.location.includes(applyFilter)) {
            return hotel.location.includes(applyFilter);
          }
          if (hotel.type.includes(applyFilter)) {
            return hotel.type.includes(applyFilter);
          }
        });
      });
    }
  }
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

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

li {
  margin: 8px 0;
}

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

del {
  color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div>
    <div class="row pt-5">
      <div class="col">
        {{filteredHotels}}
        <h5>Locations</h5>
        <label v-for="(value, key) in locations">
                {{value}}
                <input type="checkbox" :value="value" v-model="selectedLocations" :checked="isActive(value)" @click="setActive(value)">
            </label> {{selectedLocations}}
      </div>
    </div>

    <div class="row pt-5">
      <div class="col">
        <h5>Type</h5>
        <label v-for="(value, key) in types">
                {{value}}
                <input type="checkbox" :value="value" v-model="selectedTypes"
                :checked="isActive(value)"@click="setActive(value)">
            </label> {{selectedTypes}}
      </div>
    </div>

    <div class="row">
      <div class="col-sm-3 pb-4" v-for="hotel in filteredHotels">
        <div class="card text-center">
          <h1>{{hotel.name}}</h1>
          <p>{{hotel.location}}</p>
        </div>
      </div>
    </div>
  </div>
</div>

Hope this helps!

1 Comment

Please check. I've updated the answer as per the question. Now it can be filtered with location + type both together.

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.