Filtering for TreeTable
parent
0bf570cce3
commit
79785250ac
|
@ -56,7 +56,7 @@
|
||||||
<slot name="paginatorRight"></slot>
|
<slot name="paginatorRight"></slot>
|
||||||
</template>
|
</template>
|
||||||
</TTPaginator>
|
</TTPaginator>
|
||||||
<div class="p-treetable-footer" v-if="$scopedSlots.header">
|
<div class="p-treetable-footer" v-if="$scopedSlots.footer">
|
||||||
<slot name="footer"></slot>
|
<slot name="footer"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,6 +64,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 TreeTableColumnSlot from './TreeTableColumnSlot';
|
import TreeTableColumnSlot from './TreeTableColumnSlot';
|
||||||
import TreeTableRowLoader from './TreeTableRowLoader';
|
import TreeTableRowLoader from './TreeTableRowLoader';
|
||||||
|
@ -170,6 +171,14 @@ export default {
|
||||||
sortMode: {
|
sortMode: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'single'
|
default: 'single'
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
filterMode: {
|
||||||
|
type: String,
|
||||||
|
default: 'lenient'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -404,8 +413,104 @@ export default {
|
||||||
|
|
||||||
return (this.d_multiSortMeta[index].order * result);
|
return (this.d_multiSortMeta[index].order * result);
|
||||||
},
|
},
|
||||||
isNodeSelected() {
|
filter(value) {
|
||||||
return false;
|
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: {
|
computed: {
|
||||||
|
@ -436,9 +541,9 @@ export default {
|
||||||
data = this.sortMultiple(data);
|
data = this.sortMultiple(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (this.hasFilters) {
|
if (this.hasFilters) {
|
||||||
data = this.filter(data);
|
data = this.filter(data);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -477,6 +582,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');
|
||||||
|
},
|
||||||
paginatorTop() {
|
paginatorTop() {
|
||||||
return this.paginator && (this.paginatorPosition !== 'bottom' || this.paginatorPosition === 'both');
|
return this.paginator && (this.paginatorPosition !== 'bottom' || this.paginatorPosition === 'both');
|
||||||
},
|
},
|
||||||
|
|
|
@ -400,6 +400,11 @@ export default new Router({
|
||||||
path: '/treetable/sort',
|
path: '/treetable/sort',
|
||||||
name: 'treetablesort',
|
name: 'treetablesort',
|
||||||
component: () => import('./views/treetable/TreeTableSortDemo.vue')
|
component: () => import('./views/treetable/TreeTableSortDemo.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/treetable/filter',
|
||||||
|
name: 'treetablefilter',
|
||||||
|
component: () => import('./views/treetable/TreeTableFilterDemo.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/tristatecheckbox',
|
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/templating">● Templating</router-link></li>
|
||||||
<li><router-link to="/treetable/paginator">● Paginator</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/sort">● Sort</router-link></li>
|
||||||
|
<li><router-link to="/treetable/filter">● Filter</router-link></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue