Filtering for DataTable
parent
ea8b67fda3
commit
f7b2492c82
|
@ -49,6 +49,14 @@ export default {
|
||||||
footerClass: {
|
footerClass: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null
|
||||||
|
},
|
||||||
|
filterMatchMode: {
|
||||||
|
type: String,
|
||||||
|
default: 'startsWith'
|
||||||
|
},
|
||||||
|
excludeGlobalFilter: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
<ColumnSlot :column="col" type="header" v-if="col.$scopedSlots.header" />
|
<ColumnSlot :column="col" type="header" v-if="col.$scopedSlots.header" />
|
||||||
<span class="p-column-title" v-if="col.header">{{col.header}}</span>
|
<span class="p-column-title" v-if="col.header">{{col.header}}</span>
|
||||||
<span v-if="col.sortable" :class="getSortableColumnIcon(col)"></span>
|
<span v-if="col.sortable" :class="getSortableColumnIcon(col)"></span>
|
||||||
|
<ColumnSlot :column="col" type="filter" v-if="col.$scopedSlots.filter" />
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -66,6 +67,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ObjectUtils from '../utils/ObjectUtils';
|
import ObjectUtils from '../utils/ObjectUtils';
|
||||||
|
import FilterUtils from '../utils/FilterUtils';
|
||||||
import DomHandler from '../utils/DomHandler';
|
import DomHandler from '../utils/DomHandler';
|
||||||
import Paginator from '../paginator/Paginator';
|
import Paginator from '../paginator/Paginator';
|
||||||
|
|
||||||
|
@ -175,6 +177,10 @@ export default {
|
||||||
sortMode: {
|
sortMode: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'single'
|
default: 'single'
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -369,6 +375,53 @@ export default {
|
||||||
this.d_multiSortMeta.push(meta);
|
this.d_multiSortMeta.push(meta);
|
||||||
|
|
||||||
this.d_multiSortMeta = [...this.d_multiSortMeta];
|
this.d_multiSortMeta = [...this.d_multiSortMeta];
|
||||||
|
},
|
||||||
|
filter(data) {
|
||||||
|
let filteredValue = [];
|
||||||
|
|
||||||
|
for(let i = 0; i < data.length; i++) {
|
||||||
|
let localMatch = true;
|
||||||
|
let globalMatch = false;
|
||||||
|
|
||||||
|
for(let j = 0; j < this.columns.length; j++) {
|
||||||
|
let col = this.columns[j];
|
||||||
|
let columnField = col.field;
|
||||||
|
|
||||||
|
//local
|
||||||
|
if (this.filters.hasOwnProperty(columnField)) {
|
||||||
|
let filterValue = this.filters[columnField];
|
||||||
|
let dataFieldValue = ObjectUtils.resolveFieldData(data[i], columnField);
|
||||||
|
let filterConstraint = FilterUtils[col.filterMatchMode];
|
||||||
|
|
||||||
|
if (!filterConstraint(dataFieldValue, filterValue)) {
|
||||||
|
localMatch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!localMatch) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!col.excludeGlobalFilter && this.hasGlobalFilter && !globalMatch) {
|
||||||
|
globalMatch = FilterUtils.contains(ObjectUtils.resolveFieldData(data[i], columnField), this.filters['global']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let matches = localMatch;
|
||||||
|
if(this.hasGlobalFilter) {
|
||||||
|
matches = localMatch && globalMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(matches) {
|
||||||
|
filteredValue.push(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filteredValue.length === data.length) {
|
||||||
|
filteredValue = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredValue;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -389,6 +442,10 @@ export default {
|
||||||
data = this.sortMultiple(data);
|
data = this.sortMultiple(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.hasFilters) {
|
||||||
|
data = this.filter(data);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.paginator) {
|
if (this.paginator) {
|
||||||
const first = this.lazy ? 0 : this.d_first;
|
const first = this.lazy ? 0 : this.d_first;
|
||||||
return data.slice(first, first + this.d_rows);
|
return data.slice(first, first + this.d_rows);
|
||||||
|
@ -431,6 +488,12 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasFooter;
|
return hasFooter;
|
||||||
|
},
|
||||||
|
hasFilters() {
|
||||||
|
return this.filters && Object.keys(this.filters).length > 0 && this.filters.constructor === Object;
|
||||||
|
},
|
||||||
|
hasGlobalFilter() {
|
||||||
|
return this.filters && this.filters.hasOwnProperty('global');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -126,6 +126,11 @@ export default new Router({
|
||||||
name: 'datatablesort',
|
name: 'datatablesort',
|
||||||
component: () => import('./views/datatable/DataTableSortDemo.vue')
|
component: () => import('./views/datatable/DataTableSortDemo.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/datatable/filter',
|
||||||
|
name: 'datatablefilter',
|
||||||
|
component: () => import('./views/datatable/DataTableFilterDemo.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/dataview',
|
path: '/dataview',
|
||||||
name: 'dataview',
|
name: 'dataview',
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<DataTableSubMenu />
|
||||||
|
|
||||||
|
<div class="content-section introduction">
|
||||||
|
<div class="feature-intro">
|
||||||
|
<h1>DataTable - Filter</h1>
|
||||||
|
<p>Filtering is enabled by defining a filter template per column to populate the filters property of the DataTable.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-section implementation">
|
||||||
|
<DataTable :value="cars" :filters="filters" :paginator="true" :rows="10">
|
||||||
|
<template #header>
|
||||||
|
<div style="text-align: right">
|
||||||
|
<i class="pi pi-search" style="margin: 4px 4px 0px 0px;"></i>
|
||||||
|
<InputText v-model="filters['global']" placeholder="Global Search" size="50" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<Column field="vin" header="Vin" filterMatchMode="startsWith">
|
||||||
|
<template #filter>
|
||||||
|
<InputText type="text" v-model="filters['vin']" class="p-column-filter" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="year" header="Year" filterMatchMode="contains">
|
||||||
|
<template #filter>
|
||||||
|
<InputText type="text" v-model="filters['year']" class="p-column-filter" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="brand" header="Brand" filterMatchMode="equals">
|
||||||
|
<template #filter>
|
||||||
|
<Dropdown v-model="filters['brand']" :options="brands" optionLabel="brand" optionValue="value" placeholder="Select a Brand" class="p-column-filter">
|
||||||
|
<template #option="slotProps">
|
||||||
|
<div class="p-clearfix p-dropdown-car-option">
|
||||||
|
<img :alt="slotProps.option.brand" :src="'demo/images/car/' + slotProps.option.brand + '.png'" />
|
||||||
|
<span>{{slotProps.option.brand}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Dropdown>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="color" header="Color" filterMatchMode="in">
|
||||||
|
<template #filter>
|
||||||
|
<MultiSelect v-model="filters['color']" :options="colors" optionLabel="name" optionValue="value" placeholder="Select a Color" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CarService from '../../service/CarService';
|
||||||
|
import DataTableSubMenu from './DataTableSubMenu';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
filters: {},
|
||||||
|
brands: [
|
||||||
|
{brand: 'Audi', value: 'Audi'},
|
||||||
|
{brand: 'BMW', value: 'BMW'},
|
||||||
|
{brand: 'Fiat', value: 'Fiat'},
|
||||||
|
{brand: 'Honda', value: 'Honda'},
|
||||||
|
{brand: 'Jaguar', value: 'Jaguar'},
|
||||||
|
{brand: 'Mercedes', value: 'Mercedes'},
|
||||||
|
{brand: 'Renault', value: 'Renault'},
|
||||||
|
{brand: 'Volkswagen', value: 'Volkswagen'},
|
||||||
|
{brand: 'Volvo', value: 'Volvo'}
|
||||||
|
],
|
||||||
|
colors: [
|
||||||
|
{name: 'White', value: 'White'},
|
||||||
|
{name: 'Green', value: 'Green'},
|
||||||
|
{name: 'Silver', value: 'Silver'},
|
||||||
|
{name: 'Black', value: 'Black'},
|
||||||
|
{name: 'Red', value: 'Red'},
|
||||||
|
{name: 'Maroon', value: 'Maroon'},
|
||||||
|
{name: 'Brown', value: 'Brown'},
|
||||||
|
{name: 'Orange', value: 'Orange'},
|
||||||
|
{name: 'Blue', value: 'Blue'}
|
||||||
|
],
|
||||||
|
cars: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
carService: null,
|
||||||
|
created() {
|
||||||
|
this.carService = new CarService();
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.carService.getCarsLarge().then(data => this.cars = data);
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
'DataTableSubMenu': DataTableSubMenu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/deep/ .p-dropdown-label {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-multiselect {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-dropdown-car-option {
|
||||||
|
img {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: .5em;
|
||||||
|
width: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
float: right;
|
||||||
|
margin-top: .125em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue