Merge pull request #4570 from FlipWarthog/PV4555
Fix #4555 - DataTable: Add nullSortOrder proppull/4604/head
commit
cde6e2b2d1
|
@ -2671,7 +2671,7 @@ export default {
|
||||||
let innerHTML = '';
|
let innerHTML = '';
|
||||||
|
|
||||||
if (this.responsiveOptions) {
|
if (this.responsiveOptions) {
|
||||||
const comparer = new Intl.Collator(undefined, { numeric: true }).compare;
|
const comparer = ObjectUtils.localeComparator();
|
||||||
let responsiveOptions = [...this.responsiveOptions].filter((o) => !!(o.breakpoint && o.numMonths)).sort((o1, o2) => -1 * comparer(o1.breakpoint, o2.breakpoint));
|
let responsiveOptions = [...this.responsiveOptions].filter((o) => !!(o.breakpoint && o.numMonths)).sort((o1, o2) => -1 * comparer(o1.breakpoint, o2.breakpoint));
|
||||||
|
|
||||||
for (let i = 0; i < responsiveOptions.length; i++) {
|
for (let i = 0; i < responsiveOptions.length; i++) {
|
||||||
|
|
|
@ -101,7 +101,7 @@ import ChevronLeftIcon from 'primevue/icons/chevronleft';
|
||||||
import ChevronRightIcon from 'primevue/icons/chevronright';
|
import ChevronRightIcon from 'primevue/icons/chevronright';
|
||||||
import ChevronUpIcon from 'primevue/icons/chevronup';
|
import ChevronUpIcon from 'primevue/icons/chevronup';
|
||||||
import Ripple from 'primevue/ripple';
|
import Ripple from 'primevue/ripple';
|
||||||
import { DomHandler, UniqueComponentId } from 'primevue/utils';
|
import { DomHandler, UniqueComponentId, ObjectUtils } from 'primevue/utils';
|
||||||
import BaseCarousel from './BaseCarousel.vue';
|
import BaseCarousel from './BaseCarousel.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -548,20 +548,13 @@ export default {
|
||||||
|
|
||||||
if (this.responsiveOptions && !this.isUnstyled) {
|
if (this.responsiveOptions && !this.isUnstyled) {
|
||||||
let _responsiveOptions = [...this.responsiveOptions];
|
let _responsiveOptions = [...this.responsiveOptions];
|
||||||
const comparer = new Intl.Collator(undefined, { numeric: true }).compare;
|
const comparer = ObjectUtils.localeComparator();
|
||||||
|
|
||||||
_responsiveOptions.sort((data1, data2) => {
|
_responsiveOptions.sort((data1, data2) => {
|
||||||
const value1 = data1.breakpoint;
|
const value1 = data1.breakpoint;
|
||||||
const value2 = data2.breakpoint;
|
const value2 = data2.breakpoint;
|
||||||
let result = null;
|
|
||||||
|
|
||||||
if (value1 == null && value2 != null) result = -1;
|
return ObjectUtils.sort(value1, value2, -1, comparer);
|
||||||
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 = comparer(value1, value2);
|
|
||||||
else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
|
|
||||||
|
|
||||||
return -1 * result;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 0; i < _responsiveOptions.length; i++) {
|
for (let i = 0; i < _responsiveOptions.length; i++) {
|
||||||
|
|
|
@ -78,6 +78,10 @@ export default {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1
|
default: 1
|
||||||
},
|
},
|
||||||
|
nullSortOrder: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
multiSortMeta: {
|
multiSortMeta: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: null
|
default: null
|
||||||
|
|
|
@ -887,6 +887,11 @@ export interface DataTableProps {
|
||||||
* Order to sort the data by default.
|
* Order to sort the data by default.
|
||||||
*/
|
*/
|
||||||
sortOrder?: number | undefined;
|
sortOrder?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Determines how null values are sorted.
|
||||||
|
* @defaultValue 1
|
||||||
|
*/
|
||||||
|
nullSortOrder?: number;
|
||||||
/**
|
/**
|
||||||
* Default sort order of an unsorted column.
|
* Default sort order of an unsorted column.
|
||||||
* @defaultValue 1
|
* @defaultValue 1
|
||||||
|
|
|
@ -341,6 +341,7 @@ export default {
|
||||||
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_nullSortOrder: this.nullSortOrder,
|
||||||
d_multiSortMeta: this.multiSortMeta ? [...this.multiSortMeta] : [],
|
d_multiSortMeta: this.multiSortMeta ? [...this.multiSortMeta] : [],
|
||||||
d_groupRowsSortMeta: null,
|
d_groupRowsSortMeta: null,
|
||||||
d_selectionKeys: null,
|
d_selectionKeys: null,
|
||||||
|
@ -381,6 +382,9 @@ export default {
|
||||||
sortOrder(newValue) {
|
sortOrder(newValue) {
|
||||||
this.d_sortOrder = newValue;
|
this.d_sortOrder = newValue;
|
||||||
},
|
},
|
||||||
|
nullSortOrder(newValue) {
|
||||||
|
this.d_nullSortOrder = newValue;
|
||||||
|
},
|
||||||
multiSortMeta(newValue) {
|
multiSortMeta(newValue) {
|
||||||
this.d_multiSortMeta = newValue;
|
this.d_multiSortMeta = newValue;
|
||||||
},
|
},
|
||||||
|
@ -530,27 +534,19 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = [...value];
|
let data = [...value];
|
||||||
let resolvedFieldDatas = new Map();
|
let resolvedFieldData = new Map();
|
||||||
|
|
||||||
for (let item of data) {
|
for (let item of data) {
|
||||||
resolvedFieldDatas.set(item, ObjectUtils.resolveFieldData(item, this.d_sortField));
|
resolvedFieldData.set(item, ObjectUtils.resolveFieldData(item, this.d_sortField));
|
||||||
}
|
}
|
||||||
|
|
||||||
const comparer = new Intl.Collator(undefined, { numeric: true }).compare;
|
const comparer = ObjectUtils.localeComparator();
|
||||||
|
|
||||||
data.sort((data1, data2) => {
|
data.sort((data1, data2) => {
|
||||||
let value1 = resolvedFieldDatas.get(data1);
|
let value1 = resolvedFieldData.get(data1);
|
||||||
let value2 = resolvedFieldDatas.get(data2);
|
let value2 = resolvedFieldData.get(data2);
|
||||||
|
|
||||||
let result = null;
|
return ObjectUtils.sort(value1, value2, this.d_sortOrder, comparer, this.d_nullSortOrder);
|
||||||
|
|
||||||
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 = comparer(value1, value2);
|
|
||||||
else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
|
|
||||||
|
|
||||||
return this.d_sortOrder * result;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
@ -579,23 +575,13 @@ export default {
|
||||||
multisortField(data1, data2, index) {
|
multisortField(data1, data2, index) {
|
||||||
const value1 = ObjectUtils.resolveFieldData(data1, this.d_multiSortMeta[index].field);
|
const value1 = ObjectUtils.resolveFieldData(data1, this.d_multiSortMeta[index].field);
|
||||||
const value2 = ObjectUtils.resolveFieldData(data2, this.d_multiSortMeta[index].field);
|
const value2 = ObjectUtils.resolveFieldData(data2, this.d_multiSortMeta[index].field);
|
||||||
let result = null;
|
const comparer = ObjectUtils.localeComparator();
|
||||||
|
|
||||||
if (typeof value1 === 'string' || value1 instanceof String) {
|
|
||||||
if (value1.localeCompare && value1 !== value2) {
|
|
||||||
const comparer = new Intl.Collator(undefined, { numeric: true }).compare;
|
|
||||||
|
|
||||||
return this.d_multiSortMeta[index].order * comparer(value1, value2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result = value1 < value2 ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value1 === value2) {
|
if (value1 === value2) {
|
||||||
return this.d_multiSortMeta.length - 1 > index ? this.multisortField(data1, data2, index + 1) : 0;
|
return this.d_multiSortMeta.length - 1 > index ? this.multisortField(data1, data2, index + 1) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.d_multiSortMeta[index].order * result;
|
return ObjectUtils.sort(value1, value2, this.d_multiSortMeta[index].order, comparer, this.d_nullSortOrder);
|
||||||
},
|
},
|
||||||
addMultiSortField(field) {
|
addMultiSortField(field) {
|
||||||
let index = this.d_multiSortMeta.findIndex((meta) => meta.field === field);
|
let index = this.d_multiSortMeta.findIndex((meta) => meta.field === field);
|
||||||
|
|
|
@ -110,20 +110,13 @@ export default {
|
||||||
sort() {
|
sort() {
|
||||||
if (this.value) {
|
if (this.value) {
|
||||||
const value = [...this.value];
|
const value = [...this.value];
|
||||||
const comparer = new Intl.Collator(undefined, { numeric: true }).compare;
|
const comparer = ObjectUtils.localeComparator();
|
||||||
|
|
||||||
value.sort((data1, data2) => {
|
value.sort((data1, data2) => {
|
||||||
let value1 = ObjectUtils.resolveFieldData(data1, this.sortField);
|
let value1 = ObjectUtils.resolveFieldData(data1, this.sortField);
|
||||||
let value2 = ObjectUtils.resolveFieldData(data2, this.sortField);
|
let value2 = ObjectUtils.resolveFieldData(data2, this.sortField);
|
||||||
let result = null;
|
|
||||||
|
|
||||||
if (value1 == null && value2 != null) result = -1;
|
return ObjectUtils.sort(value1, value2, this.sortOrder, comparer);
|
||||||
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 = comparer(value1, value2);
|
|
||||||
else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
|
|
||||||
|
|
||||||
return this.sortOrder * result;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
|
|
@ -68,7 +68,7 @@ import ChevronLeftIcon from 'primevue/icons/chevronleft';
|
||||||
import ChevronRightIcon from 'primevue/icons/chevronright';
|
import ChevronRightIcon from 'primevue/icons/chevronright';
|
||||||
import ChevronUpIcon from 'primevue/icons/chevronup';
|
import ChevronUpIcon from 'primevue/icons/chevronup';
|
||||||
import Ripple from 'primevue/ripple';
|
import Ripple from 'primevue/ripple';
|
||||||
import { DomHandler } from 'primevue/utils';
|
import { DomHandler, ObjectUtils } from 'primevue/utils';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'GalleriaThumbnails',
|
name: 'GalleriaThumbnails',
|
||||||
|
@ -438,20 +438,13 @@ export default {
|
||||||
|
|
||||||
if (this.responsiveOptions && !this.isUnstyled) {
|
if (this.responsiveOptions && !this.isUnstyled) {
|
||||||
this.sortedResponsiveOptions = [...this.responsiveOptions];
|
this.sortedResponsiveOptions = [...this.responsiveOptions];
|
||||||
const comparer = new Intl.Collator(undefined, { numeric: true }).compare;
|
const comparer = ObjectUtils.localeComparator();
|
||||||
|
|
||||||
this.sortedResponsiveOptions.sort((data1, data2) => {
|
this.sortedResponsiveOptions.sort((data1, data2) => {
|
||||||
const value1 = data1.breakpoint;
|
const value1 = data1.breakpoint;
|
||||||
const value2 = data2.breakpoint;
|
const value2 = data2.breakpoint;
|
||||||
let result = null;
|
|
||||||
|
|
||||||
if (value1 == null && value2 != null) result = -1;
|
return ObjectUtils.sort(value1, value2, -1, comparer);
|
||||||
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 = comparer(value1, value2);
|
|
||||||
else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
|
|
||||||
|
|
||||||
return -1 * result;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 0; i < this.sortedResponsiveOptions.length; i++) {
|
for (let i = 0; i < this.sortedResponsiveOptions.length; i++) {
|
||||||
|
|
|
@ -429,20 +429,13 @@ export default {
|
||||||
},
|
},
|
||||||
sortNodesSingle(nodes) {
|
sortNodesSingle(nodes) {
|
||||||
let _nodes = [...nodes];
|
let _nodes = [...nodes];
|
||||||
const comparer = new Intl.Collator(undefined, { numeric: true }).compare;
|
const comparer = ObjectUtils.localeComparator();
|
||||||
|
|
||||||
_nodes.sort((node1, node2) => {
|
_nodes.sort((node1, node2) => {
|
||||||
const value1 = ObjectUtils.resolveFieldData(node1.data, this.d_sortField);
|
const value1 = ObjectUtils.resolveFieldData(node1.data, this.d_sortField);
|
||||||
const value2 = ObjectUtils.resolveFieldData(node2.data, this.d_sortField);
|
const value2 = ObjectUtils.resolveFieldData(node2.data, this.d_sortField);
|
||||||
let result = null;
|
|
||||||
|
|
||||||
if (value1 == null && value2 != null) result = -1;
|
return ObjectUtils.sort(value1, value2, this.d_sortOrder, comparer);
|
||||||
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 = comparer(value1, value2);
|
|
||||||
else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
|
|
||||||
|
|
||||||
return this.d_sortOrder * result;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return _nodes;
|
return _nodes;
|
||||||
|
@ -462,22 +455,13 @@ export default {
|
||||||
multisortField(node1, node2, index) {
|
multisortField(node1, node2, index) {
|
||||||
const value1 = ObjectUtils.resolveFieldData(node1.data, this.d_multiSortMeta[index].field);
|
const value1 = ObjectUtils.resolveFieldData(node1.data, this.d_multiSortMeta[index].field);
|
||||||
const value2 = ObjectUtils.resolveFieldData(node2.data, this.d_multiSortMeta[index].field);
|
const value2 = ObjectUtils.resolveFieldData(node2.data, this.d_multiSortMeta[index].field);
|
||||||
let result = null;
|
const comparer = ObjectUtils.localeComparator();
|
||||||
|
|
||||||
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) {
|
if (value1 === value2) {
|
||||||
return this.d_multiSortMeta.length - 1 > index ? this.multisortField(node1, node2, index + 1) : 0;
|
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 * new Intl.Collator(undefined, { numeric: true }).compare(value1, value2);
|
|
||||||
else result = value1 < value2 ? -1 : 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.d_multiSortMeta[index].order * result;
|
return ObjectUtils.sort(value1, value2, this.d_multiSortMeta[index].order, comparer);
|
||||||
},
|
},
|
||||||
filter(value) {
|
filter(value) {
|
||||||
let filteredNodes = [];
|
let filteredNodes = [];
|
||||||
|
|
|
@ -302,6 +302,37 @@ export default {
|
||||||
return index;
|
return index;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
sort(value1, value2, order = 1, comparator, nullSortOrder = 1) {
|
||||||
|
const result = this.compare(value1, value2, comparator, order);
|
||||||
|
let finalSortOrder = order;
|
||||||
|
|
||||||
|
// nullSortOrder == 1 means Excel like sort nulls at bottom
|
||||||
|
if (this.isEmpty(value1) || this.isEmpty(value2)) {
|
||||||
|
finalSortOrder = nullSortOrder === 1 ? order : nullSortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalSortOrder * result;
|
||||||
|
},
|
||||||
|
|
||||||
|
compare(value1, value2, comparator, order = 1) {
|
||||||
|
let result = -1;
|
||||||
|
const emptyValue1 = this.isEmpty(value1);
|
||||||
|
const emptyValue2 = this.isEmpty(value2);
|
||||||
|
|
||||||
|
if (emptyValue1 && emptyValue2) result = 0;
|
||||||
|
else if (emptyValue1) result = order;
|
||||||
|
else if (emptyValue2) result = -order;
|
||||||
|
else if (typeof value1 === 'string' && typeof value2 === 'string') result = comparator(value1, value2);
|
||||||
|
else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
localeComparator() {
|
||||||
|
//performance gain using Int.Collator. It is not recommended to use localeCompare against large arrays.
|
||||||
|
return new Intl.Collator(undefined, { numeric: true }).compare;
|
||||||
|
},
|
||||||
|
|
||||||
nestedKeys(obj = {}, parentKey = '') {
|
nestedKeys(obj = {}, parentKey = '') {
|
||||||
return Object.entries(obj).reduce((o, [key, value]) => {
|
return Object.entries(obj).reduce((o, [key, value]) => {
|
||||||
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
||||||
|
|
|
@ -89,6 +89,8 @@ export declare class ObjectUtils {
|
||||||
static isPrintableCharacter(char: string): boolean;
|
static isPrintableCharacter(char: string): boolean;
|
||||||
static findLast(value: any[], callback: () => any): any;
|
static findLast(value: any[], callback: () => any): any;
|
||||||
static findLastIndex(value: any[], callback: () => any): number;
|
static findLastIndex(value: any[], callback: () => any): number;
|
||||||
|
static sort(value1: any, value2: any, order: number, comparator: (a: any, b: any) => any, nullSortOrder: number): number;
|
||||||
|
static compare(value1: any, value2: any, comparator: (a: any, b: any) => any, order: number): number;
|
||||||
static nestedKeys(obj: object, parentKey?: string): string[];
|
static nestedKeys(obj: object, parentKey?: string): string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18854,6 +18854,14 @@
|
||||||
"default": "",
|
"default": "",
|
||||||
"description": "Order to sort the data by default."
|
"description": "Order to sort the data by default."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "nullSortOrder",
|
||||||
|
"optional": true,
|
||||||
|
"readonly": false,
|
||||||
|
"type": "number",
|
||||||
|
"default": "1",
|
||||||
|
"description": "Determines how null values are sorted."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "defaultSortOrder",
|
"name": "defaultSortOrder",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
|
Loading…
Reference in New Issue