Multiple Column Sorting for DataTable

pull/14/head
cagataycivici 2019-07-02 13:15:50 +03:00
parent 3ce0a109d2
commit ae31391bb6
2 changed files with 148 additions and 34 deletions

View File

@ -158,6 +158,14 @@ export default {
defaultSortOrder: { defaultSortOrder: {
type: Number, type: Number,
default: 1 default: 1
},
multiSortMeta: {
type: Array,
default: null
},
sortMode: {
type: String,
default: 'single'
} }
}, },
data() { data() {
@ -166,7 +174,8 @@ export default {
d_first: this.first, d_first: this.first,
d_rows: this.rows, d_rows: this.rows,
d_sortField: this.sortField, d_sortField: this.sortField,
d_sortOrder: this.sortOrder d_sortOrder: this.sortOrder,
d_multiSortMeta: this.multiSortMeta ? [...this.multiSortMeta] : []
}; };
}, },
watch: { watch: {
@ -181,6 +190,9 @@ export default {
}, },
sortOrder(newValue) { sortOrder(newValue) {
this.d_sortOrder = newValue; this.d_sortOrder = newValue;
},
multiSortMeta(newValue) {
this.d_multiSortMeta = newValue;
} }
}, },
mounted() { mounted() {
@ -201,51 +213,109 @@ export default {
this.$emit('update:rows', this.d_rows); this.$emit('update:rows', this.d_rows);
this.$emit('page', event); this.$emit('page', event);
}, },
onColumnHeaderClick($event, column) { onColumnHeaderClick(event, column) {
if (column.sortable) { if (column.sortable) {
let targetNode = event.target; const targetNode = event.target;
let columnField = column.field || column.sortField; const columnField = column.field || column.sortField;
if(DomHandler.hasClass(targetNode, 'p-sortable-column') || DomHandler.hasClass(targetNode, 'p-column-title') 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.hasClass(targetNode, 'p-sortable-column-icon') || DomHandler.hasClass(targetNode.parentElement, 'p-sortable-column-icon')) {
DomHandler.clearSelection();
this.d_sortOrder = (this.d_sortField === columnField) ? this.d_sortOrder * -1 : this.defaultSortOrder; this.d_sortOrder = (this.d_sortField === columnField) ? this.d_sortOrder * -1 : this.defaultSortOrder;
this.d_sortField = columnField; this.d_sortField = columnField;
DomHandler.clearSelection();
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
});
} }
} }
}, },
sort(value) { sortSingle(value) {
if (value) { let data = [...this.value];
let data = [...this.value];
data.sort((data1, data2) => { data.sort((data1, data2) => {
let value1 = ObjectUtils.resolveFieldData(data1, this.d_sortField); let value1 = ObjectUtils.resolveFieldData(data1, this.d_sortField);
let value2 = ObjectUtils.resolveFieldData(data2, this.d_sortField); let value2 = ObjectUtils.resolveFieldData(data2, this.d_sortField);
let result = null; let result = null;
if (value1 == null && value2 != null) if (value1 == null && value2 != null)
result = -1; result = -1;
else if (value1 != null && value2 == null) else if (value1 != null && value2 == null)
result = 1; result = 1;
else if (value1 == null && value2 == null) else if (value1 == null && value2 == null)
result = 0; result = 0;
else if (typeof value1 === 'string' && typeof value2 === 'string') else if (typeof value1 === 'string' && typeof value2 === 'string')
result = value1.localeCompare(value2, undefined, { numeric: true }); result = value1.localeCompare(value2, undefined, { numeric: true });
else else
result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0; result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0;
return (this.d_sortOrder * result); return (this.d_sortOrder * result);
}); });
return data; return data;
},
sortMultiple(value) {
let data = [...this.value];
data.sort((data1, data2) => {
return this.multisortField(data1, data2, 0);
});
return data;
},
multisortField(data1, data2, index) {
const value1 = ObjectUtils.resolveFieldData(data1, this.d_multiSortMeta[index].field);
const value2 = ObjectUtils.resolveFieldData(data2, this.d_multiSortMeta[index].field);
let result = null;
if (typeof value1 === 'string' || value1 instanceof String) {
if (value1.localeCompare && (value1 !== value2)) {
return (this.d_multiSortMeta[index].order * value1.localeCompare(value2, undefined, { numeric: true }));
}
} }
else { else {
return null; result = (value1 < value2) ? -1 : 1;
} }
if (value1 === value2) {
return (this.d_multiSortMeta.length - 1) > (index) ? (this.multisortField(data1, data2, index + 1)) : 0;
}
return (this.d_multiSortMeta[index].order * result);
},
getMultiSortMetaIndex(column) {
let index = -1;
for (let i = 0; i < this.d_multiSortMeta.length; i++) {
let meta = this.d_multiSortMeta[i];
if (meta.field === (column.field || column.sortField)) {
index = i;
break;
}
}
return index;
}, },
getColumnHeaderClass(column) { getColumnHeaderClass(column) {
const sorted = this.d_sortField === (column.field || column.sortField); const sorted = this.sortMode === 'single' ? (this.d_sortField === (column.field || column.sortField)) : this.getMultiSortMetaIndex(column) > -1;
return [column.headerClass, return [column.headerClass,
{'p-sortable-column': column.sortable}, {'p-sortable-column': column.sortable},
@ -253,14 +323,43 @@ export default {
]; ];
}, },
getSortableColumnIcon(column) { getSortableColumnIcon(column) {
const sorted = this.d_sortField === (column.field || column.sortField); let sorted = false;
let sortOrder = null;
if (this.sortMode === 'single') {
sorted = this.d_sortField === (column.field || column.sortField);
sortOrder = sorted ? this.d_sortOrder: 0;
}
else if (this.sortMode === 'multiple') {
let metaIndex = this.getMultiSortMetaIndex(column);
if (metaIndex > -1) {
sorted = true;
sortOrder = this.d_multiSortMeta[metaIndex].order;
}
}
return [ return [
'p-sortable-column-icon pi pi-fw', 'p-sortable-column-icon pi pi-fw',
{'pi-sort': !sorted}, {'pi-sort': !sorted},
{'pi-sort-up': sorted && this.d_sortOrder > 0}, {'pi-sort-up': sorted && sortOrder > 0},
{'pi-sort-down': sorted && this.d_sortOrder < 0}, {'pi-sort-down': sorted && sortOrder < 0},
]; ];
},
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];
} }
}, },
computed: { computed: {
@ -274,8 +373,11 @@ export default {
if (this.value && this.value.length) { if (this.value && this.value.length) {
let data = this.value; let data = this.value;
if (data && data.length && this.d_sortField) { if (this.sorted) {
data = this.sort(data); if(this.sortMode === 'single')
data = this.sortSingle(data);
else if(this.sortMode === 'multiple')
data = this.sortMultiple(data);
} }
if (this.paginator) { if (this.paginator) {
@ -305,6 +407,9 @@ export default {
}, },
paginatorBottom() { paginatorBottom() {
return this.paginator && (this.paginatorPosition !== 'top' || this.paginatorPosition === 'both'); return this.paginator && (this.paginatorPosition !== 'top' || this.paginatorPosition === 'both');
},
sorted() {
return this.d_sortField || (this.d_multiSortMeta && this.d_multiSortMeta.length > 0);
} }
}, },
components: { components: {

View File

@ -10,12 +10,21 @@
</div> </div>
<div class="content-section implementation"> <div class="content-section implementation">
<h3 class="first">Single Column</h3>
<DataTable :value="cars"> <DataTable :value="cars">
<Column field="vin" header="Vin" :sortable="true"></Column> <Column field="vin" header="Vin" :sortable="true"></Column>
<Column field="year" header="Year" :sortable="true"></Column> <Column field="year" header="Year" :sortable="true"></Column>
<Column field="brand" header="Brand" :sortable="true"></Column> <Column field="brand" header="Brand" :sortable="true"></Column>
<Column field="color" header="Color" :sortable="true"></Column> <Column field="color" header="Color" :sortable="true"></Column>
</DataTable> </DataTable>
<h3>Multiple Columns</h3>
<DataTable :value="cars" sortMode="multiple">
<Column field="vin" header="Vin" :sortable="true"></Column>
<Column field="year" header="Year" :sortable="true"></Column>
<Column field="brand" header="Brand" :sortable="true"></Column>
<Column field="color" header="Color" :sortable="true"></Column>
</DataTable>
</div> </div>
</div> </div>
</template> </template>