Filtering for TreeTable
parent
0bf570cce3
commit
79785250ac
|
@ -56,7 +56,7 @@
|
|||
<slot name="paginatorRight"></slot>
|
||||
</template>
|
||||
</TTPaginator>
|
||||
<div class="p-treetable-footer" v-if="$scopedSlots.header">
|
||||
<div class="p-treetable-footer" v-if="$scopedSlots.footer">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -64,6 +64,7 @@
|
|||
|
||||
<script>
|
||||
import ObjectUtils from '../utils/ObjectUtils';
|
||||
import FilterUtils from '../utils/FilterUtils';
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
import TreeTableColumnSlot from './TreeTableColumnSlot';
|
||||
import TreeTableRowLoader from './TreeTableRowLoader';
|
||||
|
@ -170,6 +171,14 @@ export default {
|
|||
sortMode: {
|
||||
type: String,
|
||||
default: 'single'
|
||||
},
|
||||
filters: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
filterMode: {
|
||||
type: String,
|
||||
default: 'lenient'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -404,8 +413,104 @@ export default {
|
|||
|
||||
return (this.d_multiSortMeta[index].order * result);
|
||||
},
|
||||
isNodeSelected() {
|
||||
return false;
|
||||
filter(value) {
|
||||
let filteredNodes = [];
|
||||
const strict = this.filterMode === 'strict';
|
||||
let valueChanged = false;
|
||||
|
||||
for (let node of value) {
|
||||
let copyNode = {...node};
|
||||
let localMatch = true;
|
||||
let globalMatch = false;
|
||||
|
||||
for (let j = 0; j < this.columns.length; j++) {
|
||||
let col = this.columns[j];
|
||||
let filterField = col.field;
|
||||
|
||||
//local
|
||||
if (this.filters.hasOwnProperty(col.field)) {
|
||||
let filterMatchMode = col.filterMatchMode;
|
||||
let filterValue = this.filters[col.field];
|
||||
let filterConstraint = FilterUtils[col.filterMatchMode];
|
||||
let paramsWithoutNode = {filterField, filterValue, filterConstraint, strict};
|
||||
|
||||
if ((strict && !(this.findFilteredNodes(copyNode, paramsWithoutNode) || this.isFilterMatched(copyNode, paramsWithoutNode))) ||
|
||||
(!strict && !(this.isFilterMatched(copyNode, paramsWithoutNode) || this.findFilteredNodes(copyNode, paramsWithoutNode)))) {
|
||||
localMatch = false;
|
||||
}
|
||||
|
||||
if (!localMatch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//global
|
||||
if (this.hasGlobalFilter && !globalMatch) {
|
||||
let copyNodeForGlobal = {...copyNode};
|
||||
let globalFilterValue = this.props.globalFilter;
|
||||
let globalFilterConstraint = ObjectUtils.filterConstraints['contains'];
|
||||
paramsWithoutNode = {filterField, globalFilterValue, globalFilterConstraint, strict};
|
||||
|
||||
if ((strict && (this.findFilteredNodes(copyNodeForGlobal, paramsWithoutNode) || this.isFilterMatched(copyNodeForGlobal, paramsWithoutNode))) ||
|
||||
(!strict && (this.isFilterMatched(copyNodeForGlobal, paramsWithoutNode) || this.findFilteredNodes(copyNodeForGlobal, paramsWithoutNode)))) {
|
||||
globalMatch = true;
|
||||
copyNode = copyNodeForGlobal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let matches = localMatch;
|
||||
if (this.hasGlobalFilter) {
|
||||
matches = localMatch && globalMatch;
|
||||
}
|
||||
|
||||
if (matches) {
|
||||
filteredNodes.push(copyNode);
|
||||
}
|
||||
|
||||
valueChanged = valueChanged || !localMatch || globalMatch;
|
||||
}
|
||||
|
||||
return valueChanged ? filteredNodes : value;
|
||||
},
|
||||
findFilteredNodes(node, paramsWithoutNode) {
|
||||
if (node) {
|
||||
let matched = false;
|
||||
if (node.children) {
|
||||
let childNodes = [...node.children];
|
||||
node.children = [];
|
||||
for (let childNode of childNodes) {
|
||||
let copyChildNode = {...childNode};
|
||||
if (this.isFilterMatched(copyChildNode, paramsWithoutNode)) {
|
||||
matched = true;
|
||||
node.children.push(copyChildNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
isFilterMatched(node, {filterField, filterValue, filterConstraint, strict}) {
|
||||
let matched = false;
|
||||
let dataFieldValue = ObjectUtils.resolveFieldData(node.data, filterField);
|
||||
if (filterConstraint(dataFieldValue, filterValue)) {
|
||||
matched = true;
|
||||
}
|
||||
|
||||
if (!matched || (strict && !this.isNodeLeaf(node))) {
|
||||
matched = this.findFilteredNodes(node, {filterField, filterValue, filterConstraint, strict}) || matched;
|
||||
}
|
||||
|
||||
return matched;
|
||||
},
|
||||
isNodeSelected(node) {
|
||||
return (this.selectionMode && this.selectionKeys) ? this.selectionKeys[node.key] === true : false;
|
||||
},
|
||||
isNodeLeaf(node) {
|
||||
return node.leaf === false ? false : !(node.children && node.children.length);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -436,9 +541,9 @@ export default {
|
|||
data = this.sortMultiple(data);
|
||||
}
|
||||
|
||||
/*if (this.hasFilters) {
|
||||
if (this.hasFilters) {
|
||||
data = this.filter(data);
|
||||
}*/
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -477,6 +582,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');
|
||||
},
|
||||
paginatorTop() {
|
||||
return this.paginator && (this.paginatorPosition !== 'bottom' || this.paginatorPosition === 'both');
|
||||
},
|
||||
|
|
|
@ -400,6 +400,11 @@ export default new Router({
|
|||
path: '/treetable/sort',
|
||||
name: 'treetablesort',
|
||||
component: () => import('./views/treetable/TreeTableSortDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/treetable/filter',
|
||||
name: 'treetablefilter',
|
||||
component: () => import('./views/treetable/TreeTableFilterDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/tristatecheckbox',
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
<template>
|
||||
<div>
|
||||
<TreeTableSubMenu />
|
||||
|
||||
<div class="content-section introduction">
|
||||
<div class="feature-intro">
|
||||
<h1>TreeTable - Filter</h1>
|
||||
<p>Filtering is enabled by defining a filter template per column to populate the filters property of the TreTable.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-section implementation">
|
||||
<h3>Lenient Filter</h3>
|
||||
<TreeTable :value="nodes" :filters="filters" filterMode="lenient">
|
||||
<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="name" header="Name" :expander="true">
|
||||
<template #filter>
|
||||
<InputText type="text" v-model="filters['name']" class="p-column-filter" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="size" header="Size">
|
||||
<template #filter>
|
||||
<InputText type="text" v-model="filters['size']" class="p-column-filter" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="type" header="Type">
|
||||
<template #filter>
|
||||
<InputText type="text" v-model="filters['type']" class="p-column-filter" />
|
||||
</template>
|
||||
</Column>
|
||||
</TreeTable>
|
||||
|
||||
<h3>Strict Filter</h3>
|
||||
<TreeTable :value="nodes" :filters="filters" filterMode="strict">
|
||||
<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="name" header="Name" :expander="true">
|
||||
<template #filter>
|
||||
<InputText type="text" v-model="filters['name']" class="p-column-filter" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="size" header="Size">
|
||||
<template #filter>
|
||||
<InputText type="text" v-model="filters['size']" class="p-column-filter" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="type" header="Type">
|
||||
<template #filter>
|
||||
<InputText type="text" v-model="filters['type']" class="p-column-filter" />
|
||||
</template>
|
||||
</Column>
|
||||
</TreeTable>
|
||||
</div>
|
||||
|
||||
<TreeTableDoc />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NodeService from '../../service/NodeService';
|
||||
import TreeTableDoc from './TreeTableDoc';
|
||||
import TreeTableSubMenu from './TreeTableSubMenu';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
filters: {},
|
||||
nodes: null
|
||||
}
|
||||
},
|
||||
nodeService: null,
|
||||
created() {
|
||||
this.nodeService = new NodeService();
|
||||
},
|
||||
mounted() {
|
||||
this.nodeService.getTreeTableNodes().then(data => this.nodes = data);
|
||||
},
|
||||
components: {
|
||||
'TreeTableDoc': TreeTableDoc,
|
||||
'TreeTableSubMenu': TreeTableSubMenu
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -5,6 +5,7 @@
|
|||
<li><router-link to="/treetable/templating">● Templating</router-link></li>
|
||||
<li><router-link to="/treetable/paginator">● Paginator</router-link></li>
|
||||
<li><router-link to="/treetable/sort">● Sort</router-link></li>
|
||||
<li><router-link to="/treetable/filter">● Filter</router-link></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue