Home > Blockchain >  How to filter data array based on user input (array as well) in Vue
How to filter data array based on user input (array as well) in Vue

Time:09-21

everybody. I have data coming to Vue app from WP back-end via WP-API. They are gathered in object 'Bookers'. I have some fields to display in each item (booker). For example Paying Systems: Visa, Mastercard, Bitcoin Cash, etc. (They are stored in bookers.acf.pay_systems) And I want to have an opportunity to filter "Bookers" items based on user input. User choose "Visa" and "Mastercard" - and I want to leave only items bookers which have Paying Systems: Visa and Mastercard. Ordinary behavior. So I have check-boxes set to take user input:

<label><input  type="checkbox" value="Visa" id="visa-check" v-model="visaCheck" /> Visa</label>\
<label><input  type="checkbox" value="Mastercard" id="mastercard-check" v-model="mastercardCheck" /> Mastercard</label>\

I have data:

data: {
   bookers: [], //data coming from WP-API
   paysysValues: [], // array to store user input
   visaCheck: false, mastercardCheck: false, appleCheck: false, googleCheck: false,bitcoinCheck: 
   false,kievstarCheck: false, privat24Check: false, // to catch user input event, if all are false filters are clear and we display original data
}

Displaying data:

<div  v-for="booker in filteredBookers"> {{booker}} <div>\

And I have computed property to display filtered/unfiltered data:

computed: {        
    filteredBookers: function () {
        //find all checked paying systems and pass them to paysysValues array
        var paysysChecks = document.querySelectorAll('.paysys-check');
        for (var i = 0; i < paysysChecks.length; i  ) {
          if (paysysChecks[i].checked) {
             this.paysysValues.push(paysysChecks[i].value);                            
          }
        }
        // checking user input event to update calculated property via reactive behavior                    
        if ( !this.visaCheck & !this.mastercardCheck & !this.appleCheck & !this.googleCheck & !this.bitcoinCheck & !this.kievstarCheck & !this.privat24Check) {
           return this.bookers
           } else {
         // and here I'm trying to compare user input array (paysysValues) with paying systems set 
         // for each booker and filter data only if we have intersection                        
              return this.bookers.filter(function (item) {
              return item.acf.pay_systems.filter(x => this.paysysValues.includes(x));
           })
         }
     }
},

And if I use to filter condition some particular value, for example item.acf.pay_systems.filter[0] == 'Visa' everything work well. But then I try to use intersection of two array it doesn't work. So, guys, please tell me what am I doing wrong

CodePudding user response:

Vue offers more cleaner ways to organise such a functionality with no for loops, querySelectors and that complicated data and computed prop.

CodePudding user response:

If I understood you correctly try like following snippet:

new Vue({
  el: '#demo',
  data() {
    return {
      bookers: [{acf: {pay_systems: ['visaCheck', 'googleCheck'],}}, {acf: {pay_systems: ['visaCheck'],}}, {acf: {pay_systems: ['bitcoinCheck', 'kievstarCheck'],}}, {acf: {pay_systems: ['appleCheck', 'bitcoinCheck'],}}], 
      values: [{name: 'visaCheck', state: false}, {name: 'mastercardCheck', state: false}, {name:  'appleCheck', state: false}, {name: 'googleCheck', state: false}, {name: 'bitcoinCheck', state: 
 false}, {name: 'kievstarCheck', state: false}, {name: 'privat24Check', state: false}]
    }
  },
  computed: {        
    filteredBookers() {    
      let chosen = this.values.filter(v => v.state).map(c => c.name)
      if (this.values.every(v => !v.state)) {
        return this.bookers
      } else {     
        return this.bookers.filter((item) => {
          return item.acf.pay_systems.some(x => chosen.includes(x));
      })
    }
  }
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
  <div v-for="item in values" :key="item.name">
    <label>
      <input  type="checkbox" v-model="item.state" />
      {{ item.name }}
    </label>
  </div>
  <div  v-for="(booker, i) in filteredBookers" :key="i">
    {{ booker }}
  </div>
</div>

  • Related