I'm using Vue2.js
and Element UI
as a framework. I would like to be able to filter a table which is sliced. To do so, I use the table
and filter
components whose documentation could be found here.
The table is not sliced. When you picked a filter, a loop goes trough each row and check if the value of the column is equal to the filter.
The table is sliced. When you picked a filter, a loop goes trough each row that results of the slice and check if the value of the column is equal to the filter. By doing that we don't filter the "hidden" values.
I've made a little https://jsfiddle.net/acm3q6q8/3/ so it is easier to understand.
All of this make sense since I'm not working on the whole data, but on a sliced version.
One solution could be to hide rows instead of excluding them by slicing the data, but I'm wondering if there is a better solution ?
jsfiddle
, display only 2 items.tag
to display only rows whose tag is Office
There is no row displayed since the row whose tag
was office was not part of the sliced table.
When filtering, I would like to take into account rows that are not necessarily displayed.
This should work fine with a multiple filter (ie I select several tags)
In the same extent if you want to sort the name by alphabetical order, Albert won't be displayed if you displayed only 2 items.
You can handle the filter-change
event on the table component (documented here), and filter/slice yourself.
var Main = {
data() {
return {
numberItemToShow : 4,
tableData: [...],
filter: []
}
},
computed : {
filterData() {
if (!this.filter.length)
return this.tableData.slice(0, this.numberItemToShow)
else
return this.tableData
.filter(row => this.filter.includes(row.tag))
.slice(0, this.numberItemToShow);
}
},
methods: {
onFilterChange(filters){
if (filters.tag)
this.filter = filters.tag;
}
}
}
And the template
<template>
<input v-model="numberItemToShow" placeholder="edit me">
<p>Number of item to display: {{ numberItemToShow }}</p>
<el-table ref="tab" :data="filterData" border style="width: 100%" @filter-change="onFilterChange">
<el-table-column prop="name" label="Name" sortable>
</el-table-column>
<el-table-column prop="tag" label="Tag" column-key="tag" :filters="[{ text: 'Home', value: 'Home' }, { text: 'Office', value: 'Office' }]">
<template scope="scope">
<el-tag :type="scope.row.tag === 'Home' ? 'primary' : 'success'" close-transition>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
</el-table>
</template>
Example.
The problem is that the slicing is done before the filtering. The filter has to see the original data, and the row-counting must be part of the filtering.
Since the filter looks at one row at a time, keeping track of the matched rows is a little tricky. What I did here is keep a counter of matched rows that resets to zero when the row being looked at is the first row of data. This is hacky, but it works. There may be a better way; I am not familiar with the table widget.
var Main = {
data() {
return {
numberItemToShow : 4,
tableData: [{
name: 'One',
tag: 'Home'
}, {
name: 'Two',
tag: 'Home'
}, {
name: 'Three',
tag: 'Home'
}, {
name: 'Four',
tag: 'Office'
}],
scratchCounter: 0
}
},
methods: {
filterTag(value, row) {
const matched = row.tag === value;
if (row === this.tableData[0]) {
this.scratchCounter = 0;
}
if (matched) {
++this.scratchCounter;
}
return this.scratchCounter <= this.numberItemToShow && matched;
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
@import url("//unpkg.com/element-ui/lib/theme-default/index.css");
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/element-ui/lib/index.js"></script>
<div id="app">
<template>
<input v-model="numberItemToShow" placeholder="edit me">
<p>Number of item to display: {{ numberItemToShow }}</p>
<el-table :data="tableData" border style="width: 100%">
<el-table-column prop="name" label="Name">
</el-table-column>
<el-table-column prop="tag" label="Tag" :filters="[{ text: 'Home', value: 'Home' }, { text: 'Office', value: 'Office' }]" :filter-method="filterTag">
<template scope="scope">
<el-tag :type="scope.row.tag === 'Home' ? 'primary' : 'success'" close-transition>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
</el-table>
</template>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With