Sorting for TreeTable

pull/41/head
cagataycivici 2019-08-07 10:31:44 +03:00
parent ce2186fe30
commit 0bf570cce3
5 changed files with 216 additions and 3 deletions

View File

@ -963,6 +963,10 @@ export default {
padding: .25em .5em; padding: .25em .5em;
} }
.p-datatable .p-column-title {
user-select: none;
}
.p-datatable .p-sortable-column { .p-datatable .p-sortable-column {
cursor: pointer; cursor: pointer;
} }

View File

@ -63,6 +63,8 @@
</template> </template>
<script> <script>
import ObjectUtils from '../utils/ObjectUtils';
import DomHandler from '../utils/DomHandler';
import TreeTableColumnSlot from './TreeTableColumnSlot'; import TreeTableColumnSlot from './TreeTableColumnSlot';
import TreeTableRowLoader from './TreeTableRowLoader'; import TreeTableRowLoader from './TreeTableRowLoader';
import Paginator from '../paginator/Paginator'; import Paginator from '../paginator/Paginator';
@ -276,8 +278,131 @@ export default {
return index; return index;
}, },
onColumnHeaderClick() { onColumnHeaderClick(event, column) {
if (column.sortable) {
this.resetPage();
const targetNode = event.target;
if (DomHandler.hasClass(targetNode, 'p-sortable-column') || DomHandler.hasClass(targetNode, 'p-column-title')
|| DomHandler.hasClass(targetNode, 'p-sortable-column-icon') || DomHandler.hasClass(targetNode.parentElement, 'p-sortable-column-icon')) {
DomHandler.clearSelection();
const columnField = column.field || column.sortField;
this.d_sortOrder = (this.d_sortField === columnField) ? this.d_sortOrder * -1 : this.defaultSortOrder;
this.d_sortField = columnField;
if(this.sortMode === 'multiple') {
let metaKey = event.metaKey || event.ctrlKey;
if (!metaKey) {
this.d_multiSortMeta = [];
}
this.addSortMeta({field: this.d_sortField, order: this.d_sortOrder});
}
this.$emit('update:sortField', this.d_sortFied);
this.$emit('update:sortOrder', this.d_sortOrder);
this.$emit('update:multiSortMeta', this.d_multiSortMeta);
this.$emit('sort', {
originalEvent: event,
sortField: this.d_sortField,
sortOrder: this.d_sortOrder,
multiSortMeta: this.d_multiSortMeta
});
}
}
},
addSortMeta(meta) {
let index = -1;
for (let i = 0; i < this.d_multiSortMeta.length; i++) {
if (this.d_multiSortMeta[i].field === meta.field) {
index = i;
break;
}
}
if(index >= 0)
this.d_multiSortMeta[index] = meta;
else
this.d_multiSortMeta.push(meta);
this.d_multiSortMeta = [...this.d_multiSortMeta];
},
sortSingle(nodes) {
return this.sortNodes(nodes);
},
sortNodesSingle(nodes) {
let _nodes = [...nodes];
_nodes.sort((node1, node2) => {
const value1 = ObjectUtils.resolveFieldData(node1.data, this.d_sortField);
const value2 = ObjectUtils.resolveFieldData(node2.data, this.d_sortField);
let result = null;
if (value1 == null && value2 != null)
result = -1;
else if (value1 != null && value2 == null)
result = 1;
else if (value1 == null && value2 == null)
result = 0;
else if (typeof value1 === 'string' && typeof value2 === 'string')
result = value1.localeCompare(value2, undefined, { numeric: true });
else
result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0;
return (this.d_sortOrder * result);
});
for (let i = 0; i < _nodes.length; i++) {
if (_nodes[i].children && _nodes[i].children.length) {
_nodes[i].children = this.sortNodesSingle(_nodes[i].children);
}
}
return _nodes;
},
sortMultiple(nodes) {
return this.sortNodesMultiple(nodes);
},
sortNodesMultiple(nodes) {
let _nodes = [...nodes];
_nodes.sort((node1, node2) => {
return this.multisortField(node1, node2, 0);
});
for (let i = 0; i < _nodes.length; i++) {
if (_nodes[i].children && _nodes[i].children.length) {
_nodes[i].children = this.sortNodesMultiple(_nodes[i].children);
}
}
return _nodes;
},
multisortField(node1, node2, index) {
const value1 = ObjectUtils.resolveFieldData(node1.data, this.d_multiSortMeta[index].field);
const value2 = ObjectUtils.resolveFieldData(node2.data, this.d_multiSortMeta[index].field);
let result = null;
if (value1 == null && value2 != null)
result = -1;
else if (value1 != null && value2 == null)
result = 1;
else if (value1 == null && value2 == null)
result = 0;
else {
if (value1 === value2) {
return (this.d_multiSortMeta.length - 1) > (index) ? (this.multisortField(node1, node2, index + 1)) : 0;
}
else {
if ((typeof value1 === 'string' || value1 instanceof String) && (typeof value2 === 'string' || value2 instanceof String))
return (this.d_multiSortMeta[index].order * value1.localeCompare(value2, undefined, { numeric: true }));
else
result = (value1 < value2) ? -1 : 1;
}
}
return (this.d_multiSortMeta[index].order * result);
}, },
isNodeSelected() { isNodeSelected() {
return false; return false;
@ -297,7 +422,30 @@ export default {
return []; return [];
}, },
processedData() { processedData() {
if (this.lazy) {
return this.value; return this.value;
}
else {
if (this.value && this.value.length) {
let data = this.value;
if (this.sorted) {
if(this.sortMode === 'single')
data = this.sortSingle(data);
else if(this.sortMode === 'multiple')
data = this.sortMultiple(data);
}
/*if (this.hasFilters) {
data = this.filter(data);
}*/
return data;
}
else {
return null;
}
}
}, },
dataToRender() { dataToRender() {
const data = this.processedData; const data = this.processedData;
@ -314,6 +462,9 @@ export default {
const data = this.processedData; const data = this.processedData;
return (!data || data.length === 0); return (!data || data.length === 0);
}, },
sorted() {
return this.d_sortField || (this.d_multiSortMeta && this.d_multiSortMeta.length > 0);
},
hasFooter() { hasFooter() {
let hasFooter = false; let hasFooter = false;
@ -374,6 +525,7 @@ export default {
.p-treetable .p-treetable-thead > tr > th .p-column-title { .p-treetable .p-treetable-thead > tr > th .p-column-title {
vertical-align: middle; vertical-align: middle;
user-select: none;
} }
.p-treetable .p-sortable-column { .p-treetable .p-sortable-column {

View File

@ -395,6 +395,11 @@ export default new Router({
path: '/treetable/paginator', path: '/treetable/paginator',
name: 'treetablepaginator', name: 'treetablepaginator',
component: () => import('./views/treetable/TreeTablePaginatorDemo.vue') component: () => import('./views/treetable/TreeTablePaginatorDemo.vue')
},
{
path: '/treetable/sort',
name: 'treetablesort',
component: () => import('./views/treetable/TreeTableSortDemo.vue')
}, },
{ {
path: '/tristatecheckbox', path: '/tristatecheckbox',

View File

@ -0,0 +1,51 @@
<template>
<div>
<TreeTableSubMenu />
<div class="content-section introduction">
<div class="feature-intro">
<h1>TreeTable - Sort</h1>
<p>TreeTable supports both single column and multiple column sorting..</p>
</div>
</div>
<div class="content-section implementation">
<h3>Single Column Sorting</h3>
<TreeTable :value="nodes" sortMode="single">
<Column field="name" header="Name" :expander="true" :sortable="true"></Column>
<Column field="size" header="Size" :sortable="true"></Column>
<Column field="type" header="Type" :sortable="true"></Column>
</TreeTable>
<h3>Multiple Column Sorting</h3>
<TreeTable :value="nodes" sortMode="multiple">
<Column field="name" header="Name" :expander="true" :sortable="true"></Column>
<Column field="size" header="Size" :sortable="true"></Column>
<Column field="type" header="Type" :sortable="true"></Column>
</TreeTable>
</div>
</div>
</template>
<script>
import NodeService from '../../service/NodeService';
import TreeTableSubMenu from './TreeTableSubMenu';
export default {
data() {
return {
nodes: null
}
},
nodeService: null,
created() {
this.nodeService = new NodeService();
},
mounted() {
this.nodeService.getTreeTableNodes().then(data => this.nodes = data);
},
components: {
'TreeTableSubMenu': TreeTableSubMenu
}
}
</script>

View File

@ -4,6 +4,7 @@
<li><router-link to="/treetable">&#9679; Documentation</router-link></li> <li><router-link to="/treetable">&#9679; Documentation</router-link></li>
<li><router-link to="/treetable/templating">&#9679; Templating</router-link></li> <li><router-link to="/treetable/templating">&#9679; Templating</router-link></li>
<li><router-link to="/treetable/paginator">&#9679; Paginator</router-link></li> <li><router-link to="/treetable/paginator">&#9679; Paginator</router-link></li>
<li><router-link to="/treetable/sort">&#9679; Sort</router-link></li>
</ul> </ul>
</div> </div>
</template> </template>