基于几个Multiselect框过滤结果,vue
FIltering results based on several Multiselect boxes, vue
我有一个 vue 组件,目前我在其中成功地显示了数据对象的结果,而且我还成功地创建了几个 multiselect 框。我的问题是过滤。
我知道如何从 multiselect 中设置单个值并比较它(使用 v-if)以便在 HTML div 中显示某些结果,但我现在完全迷失了如何基于多个 Multiselects 进行适当的过滤(特别是因为其中几个允许将值存储在数组中的多个选项)
我将我的代码片段放在下面,但我怎样才能正确地制作它,以便我可以根据 multiselects 的相应 v 模型中的所有值过滤结果,同时确保如果“所有商店”或“所有区域”是 selected,它允许 selection?
的所有值
-- 换句话说,如果用户不输入 selection 并且 multiselect 留在占位符上,则 select 的所有值都将是允许在 DOM 中显示(首先基于其他过滤器)
new Vue({
el: "#app",
components: {Multiselect: window.VueMultiselect.default},
data: {
selectedOutput: '',
selectedAreas:[],
selectedStores: [],
selectedCategories: [],
selectedShifts: [],
shifts: [
{id: 1, name: "First"},
{id: 2, name: "Second"}
],
categories: [
{id: 1, name: "electronics"},
{id: 1, name: "home"},
{id: 1, name: "auto"},
],
outputOptions: [
{id:1, name: "Sold"},
{id:2, name: "Purchased"}
],
areas: [
{value: 1, name: "East"},
{value: 1, name: "West"},
],
stores: [
{value: 1, name: "One"},
{value: 2, name: "Two"}
],
workNumbers: [
{
"Adam": {
"name": "Adam",
"title": "Manager",
"shift": "First",
"category": "electronics",
"area" : "East",
"store": "One",
"sold": 140,
"purchased": 15
},
"Ben": {
"name": "Ben",
"title": "Manager",
"shift": "First",
"category": "electronics",
"area" : "East",
"store": "One",
"sold": 225,
"purchased": 77
},
"Suzie": {
"name": "Suzie",
"title": "Manager",
"shift": "Second",
"category": "home",
"area" : "West",
"store": "Two",
"sold": 124,
"purchased": 55
},
"Reg": {
"name": "Reg",
"title": "Manager",
"shift": "Second",
"category": "home",
"area" : "West",
"store": "Two",
"sold": 66,
"purchased": 36
},
"Kelly": {
"name": "Kelly",
"title": "Manager",
"shift": "Second",
"category": "home",
"area" : "West",
"store": "Two",
"sold": 55,
"purchased": 2
},
}
]
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-multiselect/3.0.0-alpha.2/vue-multiselect.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vue-multiselect/3.0.0-alpha.2/dist/vue-multiselect.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedOutput"
:options="outputOptions"
:multiple="false"
:close-on-select="true"
label="name"
track-by="name"
@input="checkOutput"
></multiselect>
</div>
<div class="uk-width-2-10" style="position:relative;">
<multiselect
v-model="selectedShifts"
:options="shifts"
:multiple="true"
:close-on-select="true"
placeholder="All shifts"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedCategories"
:options="categories"
:multiple="true"
:close-on-select="true"
placeholder="All categories"
label="name"
track-by="id"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedAreas"
:options="areas"
:multiple="true"
:close-on-select="true"
placeholder="All areas"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedstores"
:options="stores"
:multiple="true"
:close-on-select="true"
placeholder="All stores"
label="name"
track-by="value"
></multiselect>
</div>
<table>
<tbody v-if="selectedOutput.name === 'Sold'">
<tr v-for="(value, employee) in workNumbers" :key="employee">
<!-- this is where I need a condition to show based on filters, I believe-->
<td>{{name}} - {{sold}}</td>
</tr>
</tbody>
<tbody v-else-if="selectedOutput.name === 'Purchased'">
<tr v-for="(value, employee) in workNumbers" :key="employee">
<!-- this is where I need a condition to show based on filters, I believe-->
<td>{{name}} - {{purchased}}</td>
</tr>
</tbody>
</table>
</div>
更新:
现在我转到另一个 table,它很相似,但它围绕不同的对象循环,以创建一个不同的模型,该模型也通过模态函数传递。
<tbody v-if="selectedOutput.name === 'Cubes'">
<tr v-for="(value, employee) in workNumbers" :key="employee">
<td v-for="date in dates" :key="date" >
<div v-for="(dateSpecificData, dateValue) in value.dates" :key="dateValue" @click="showModal(dateSpecificData)" :style="'background: ' + (dateSpecificData.unavailable > 0 ? '#f7a7a3' : '#a8f0c6')">
<div v-if="dateValue == date ">
@{{dateSpecificData.sold}}
</div>
</div>
</td>
</tr>
</tbody>
你可以根据参数定义一个computed-property
,returns过滤列表:
new Vue({
el: "#app",
components: { Multiselect: window.VueMultiselect.default },
data: () => ({
selectedOutput: '',
outputOptions: [ {id:1, name: "Sold"}, {id:2, name: "Purchased"} ],
selectedShifts: [],
shifts: [ {id: 1, name: "First"}, {id: 2, name: "Second"} ],
selectedCategories: [],
categories: [ {id: 1, name: "electronics"}, {id: 2, name: "home"}, {id: 3, name: "auto"} ],
selectedAreas:[],
areas: [ {value: 1, name: "East"}, {value: 1, name: "West"} ],
selectedStores: [],
stores: [ {value: 1, name: "One"}, {value: 2, name: "Two"} ],
workNumbers: [
{
"Adam": { "name": "Adam", "title": "Manager", "shift": "First", "category": "electronics", "area" : "East", "store": "One", "sold": 140, "purchased": 15 },
"Ben": { "name": "Ben", "title": "Manager", "shift": "First", "category": "home", "area" : "West", "store": "Two", "sold": 225, "purchased": 77 },
"Suzie": { "name": "Suzie", "title": "Manager", "shift": "Second", "category": "electronics", "area" : "East", "store": "One", "sold": 124, "purchased": 55 },
"Reg": { "name": "Reg", "title": "Manager", "shift": "Second", "category": "home", "area" : "West", "store": "Two", "sold": 66, "purchased": 36 },
"Kelly": { "name": "Kelly", "title": "Manager", "shift": "Second", "category": "auto", "area" : "West", "store": "Two", "sold": 55, "purchased": 2 }
}
]
}),
methods: {
filtedSelectedHelper(arr = [], val) {
return arr.length ? arr.some(({ name }) => name === val) : true;
}
},
computed: {
filteredWorkNumbers () {
const ouput = this.selectedOutput;
const filteredList =
this.workNumbers
.flatMap(Object.values)
.filter(({ shift, category, area, store }) =>
this.filtedSelectedHelper(this.selectedShifts, shift) &&
this.filtedSelectedHelper(this.selectedCategories, category) &&
this.filtedSelectedHelper(this.selectedAreas, area) &&
this.filtedSelectedHelper(this.selectedStores, store)
);
return !this.selectedOutput
? filteredList.map(({ name, sold, purchased }) =>
`${name} - ${sold} - ${purchased}`
)
: this.selectedOutput.name === "Sold"
? filteredList.map(({ name, sold }) =>
`${name} - ${sold}`
)
: filteredList.map(({ name, purchased }) =>
`${name} - ${purchased}`
)
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-multiselect@2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect@2.1.0/dist/vue-multiselect.min.css">
<div id="app">
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedOutput"
:options="outputOptions"
:multiple="false"
:close-on-select="true"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position:relative;">
<multiselect
v-model="selectedShifts"
:options="shifts"
:multiple="true"
:close-on-select="true"
placeholder="All shifts"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedCategories"
:options="categories"
:multiple="true"
:close-on-select="true"
placeholder="All categories"
label="name"
track-by="id"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedAreas"
:options="areas"
:multiple="true"
:close-on-select="true"
placeholder="All areas"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedStores"
:options="stores"
:multiple="true"
:close-on-select="true"
placeholder="All stores"
label="name"
track-by="value"
></multiselect>
</div>
<table>
<tbody>
<tr v-for="str in filteredWorkNumbers" :key="str"><td>{{str}}</td></tr>
</tbody>
</table>
</div>
资源:
https://vuejs.org/v2/guide/computed.html
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
我有一个 vue 组件,目前我在其中成功地显示了数据对象的结果,而且我还成功地创建了几个 multiselect 框。我的问题是过滤。
我知道如何从 multiselect 中设置单个值并比较它(使用 v-if)以便在 HTML div 中显示某些结果,但我现在完全迷失了如何基于多个 Multiselects 进行适当的过滤(特别是因为其中几个允许将值存储在数组中的多个选项)
我将我的代码片段放在下面,但我怎样才能正确地制作它,以便我可以根据 multiselects 的相应 v 模型中的所有值过滤结果,同时确保如果“所有商店”或“所有区域”是 selected,它允许 selection?
的所有值-- 换句话说,如果用户不输入 selection 并且 multiselect 留在占位符上,则 select 的所有值都将是允许在 DOM 中显示(首先基于其他过滤器)
new Vue({
el: "#app",
components: {Multiselect: window.VueMultiselect.default},
data: {
selectedOutput: '',
selectedAreas:[],
selectedStores: [],
selectedCategories: [],
selectedShifts: [],
shifts: [
{id: 1, name: "First"},
{id: 2, name: "Second"}
],
categories: [
{id: 1, name: "electronics"},
{id: 1, name: "home"},
{id: 1, name: "auto"},
],
outputOptions: [
{id:1, name: "Sold"},
{id:2, name: "Purchased"}
],
areas: [
{value: 1, name: "East"},
{value: 1, name: "West"},
],
stores: [
{value: 1, name: "One"},
{value: 2, name: "Two"}
],
workNumbers: [
{
"Adam": {
"name": "Adam",
"title": "Manager",
"shift": "First",
"category": "electronics",
"area" : "East",
"store": "One",
"sold": 140,
"purchased": 15
},
"Ben": {
"name": "Ben",
"title": "Manager",
"shift": "First",
"category": "electronics",
"area" : "East",
"store": "One",
"sold": 225,
"purchased": 77
},
"Suzie": {
"name": "Suzie",
"title": "Manager",
"shift": "Second",
"category": "home",
"area" : "West",
"store": "Two",
"sold": 124,
"purchased": 55
},
"Reg": {
"name": "Reg",
"title": "Manager",
"shift": "Second",
"category": "home",
"area" : "West",
"store": "Two",
"sold": 66,
"purchased": 36
},
"Kelly": {
"name": "Kelly",
"title": "Manager",
"shift": "Second",
"category": "home",
"area" : "West",
"store": "Two",
"sold": 55,
"purchased": 2
},
}
]
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-multiselect/3.0.0-alpha.2/vue-multiselect.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vue-multiselect/3.0.0-alpha.2/dist/vue-multiselect.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedOutput"
:options="outputOptions"
:multiple="false"
:close-on-select="true"
label="name"
track-by="name"
@input="checkOutput"
></multiselect>
</div>
<div class="uk-width-2-10" style="position:relative;">
<multiselect
v-model="selectedShifts"
:options="shifts"
:multiple="true"
:close-on-select="true"
placeholder="All shifts"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedCategories"
:options="categories"
:multiple="true"
:close-on-select="true"
placeholder="All categories"
label="name"
track-by="id"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedAreas"
:options="areas"
:multiple="true"
:close-on-select="true"
placeholder="All areas"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedstores"
:options="stores"
:multiple="true"
:close-on-select="true"
placeholder="All stores"
label="name"
track-by="value"
></multiselect>
</div>
<table>
<tbody v-if="selectedOutput.name === 'Sold'">
<tr v-for="(value, employee) in workNumbers" :key="employee">
<!-- this is where I need a condition to show based on filters, I believe-->
<td>{{name}} - {{sold}}</td>
</tr>
</tbody>
<tbody v-else-if="selectedOutput.name === 'Purchased'">
<tr v-for="(value, employee) in workNumbers" :key="employee">
<!-- this is where I need a condition to show based on filters, I believe-->
<td>{{name}} - {{purchased}}</td>
</tr>
</tbody>
</table>
</div>
更新:
现在我转到另一个 table,它很相似,但它围绕不同的对象循环,以创建一个不同的模型,该模型也通过模态函数传递。
<tbody v-if="selectedOutput.name === 'Cubes'">
<tr v-for="(value, employee) in workNumbers" :key="employee">
<td v-for="date in dates" :key="date" >
<div v-for="(dateSpecificData, dateValue) in value.dates" :key="dateValue" @click="showModal(dateSpecificData)" :style="'background: ' + (dateSpecificData.unavailable > 0 ? '#f7a7a3' : '#a8f0c6')">
<div v-if="dateValue == date ">
@{{dateSpecificData.sold}}
</div>
</div>
</td>
</tr>
</tbody>
你可以根据参数定义一个computed-property
,returns过滤列表:
new Vue({
el: "#app",
components: { Multiselect: window.VueMultiselect.default },
data: () => ({
selectedOutput: '',
outputOptions: [ {id:1, name: "Sold"}, {id:2, name: "Purchased"} ],
selectedShifts: [],
shifts: [ {id: 1, name: "First"}, {id: 2, name: "Second"} ],
selectedCategories: [],
categories: [ {id: 1, name: "electronics"}, {id: 2, name: "home"}, {id: 3, name: "auto"} ],
selectedAreas:[],
areas: [ {value: 1, name: "East"}, {value: 1, name: "West"} ],
selectedStores: [],
stores: [ {value: 1, name: "One"}, {value: 2, name: "Two"} ],
workNumbers: [
{
"Adam": { "name": "Adam", "title": "Manager", "shift": "First", "category": "electronics", "area" : "East", "store": "One", "sold": 140, "purchased": 15 },
"Ben": { "name": "Ben", "title": "Manager", "shift": "First", "category": "home", "area" : "West", "store": "Two", "sold": 225, "purchased": 77 },
"Suzie": { "name": "Suzie", "title": "Manager", "shift": "Second", "category": "electronics", "area" : "East", "store": "One", "sold": 124, "purchased": 55 },
"Reg": { "name": "Reg", "title": "Manager", "shift": "Second", "category": "home", "area" : "West", "store": "Two", "sold": 66, "purchased": 36 },
"Kelly": { "name": "Kelly", "title": "Manager", "shift": "Second", "category": "auto", "area" : "West", "store": "Two", "sold": 55, "purchased": 2 }
}
]
}),
methods: {
filtedSelectedHelper(arr = [], val) {
return arr.length ? arr.some(({ name }) => name === val) : true;
}
},
computed: {
filteredWorkNumbers () {
const ouput = this.selectedOutput;
const filteredList =
this.workNumbers
.flatMap(Object.values)
.filter(({ shift, category, area, store }) =>
this.filtedSelectedHelper(this.selectedShifts, shift) &&
this.filtedSelectedHelper(this.selectedCategories, category) &&
this.filtedSelectedHelper(this.selectedAreas, area) &&
this.filtedSelectedHelper(this.selectedStores, store)
);
return !this.selectedOutput
? filteredList.map(({ name, sold, purchased }) =>
`${name} - ${sold} - ${purchased}`
)
: this.selectedOutput.name === "Sold"
? filteredList.map(({ name, sold }) =>
`${name} - ${sold}`
)
: filteredList.map(({ name, purchased }) =>
`${name} - ${purchased}`
)
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-multiselect@2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect@2.1.0/dist/vue-multiselect.min.css">
<div id="app">
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedOutput"
:options="outputOptions"
:multiple="false"
:close-on-select="true"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position:relative;">
<multiselect
v-model="selectedShifts"
:options="shifts"
:multiple="true"
:close-on-select="true"
placeholder="All shifts"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedCategories"
:options="categories"
:multiple="true"
:close-on-select="true"
placeholder="All categories"
label="name"
track-by="id"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedAreas"
:options="areas"
:multiple="true"
:close-on-select="true"
placeholder="All areas"
label="name"
track-by="name"
></multiselect>
</div>
<div class="uk-width-2-10" style="position: relative !important;">
<multiselect
v-model="selectedStores"
:options="stores"
:multiple="true"
:close-on-select="true"
placeholder="All stores"
label="name"
track-by="value"
></multiselect>
</div>
<table>
<tbody>
<tr v-for="str in filteredWorkNumbers" :key="str"><td>{{str}}</td></tr>
</tbody>
</table>
</div>
资源:
https://vuejs.org/v2/guide/computed.html
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map