Filtering for DataTable
parent
ea8b67fda3
commit
f7b2492c82
|
@ -49,6 +49,14 @@ export default {
|
|||
footerClass: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
filterMatchMode: {
|
||||
type: String,
|
||||
default: 'startsWith'
|
||||
},
|
||||
excludeGlobalFilter: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
render() {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<ColumnSlot :column="col" type="header" v-if="col.$scopedSlots.header" />
|
||||
<span class="p-column-title" v-if="col.header">{{col.header}}</span>
|
||||
<span v-if="col.sortable" :class="getSortableColumnIcon(col)"></span>
|
||||
<ColumnSlot :column="col" type="filter" v-if="col.$scopedSlots.filter" />
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -66,6 +67,7 @@
|
|||
|
||||
<script>
|
||||
import ObjectUtils from '../utils/ObjectUtils';
|
||||
import FilterUtils from '../utils/FilterUtils';
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
import Paginator from '../paginator/Paginator';
|
||||
|
||||
|
@ -175,6 +177,10 @@ export default {
|
|||
sortMode: {
|
||||
type: String,
|
||||
default: 'single'
|
||||
},
|
||||
filters: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -369,6 +375,53 @@ export default {
|
|||
this.d_multiSortMeta.push(meta);
|
||||
|
||||
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: {
|
||||
|
@ -389,6 +442,10 @@ export default {
|
|||
data = this.sortMultiple(data);
|
||||
}
|
||||
|
||||
if (this.hasFilters) {
|
||||
data = this.filter(data);
|
||||
}
|
||||
|
||||
if (this.paginator) {
|
||||
const first = this.lazy ? 0 : this.d_first;
|
||||
return data.slice(first, first + this.d_rows);
|
||||
|
@ -431,6 +488,12 @@ export default {
|
|||
}
|
||||
|
||||
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: {
|
||||
|
|
|
@ -126,6 +126,11 @@ export default new Router({
|
|||
name: 'datatablesort',
|
||||
component: () => import('./views/datatable/DataTableSortDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/datatable/filter',
|
||||
name: 'datatablefilter',
|
||||
component: () => import('./views/datatable/DataTableFilterDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/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