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>