Fix sorting with empty strings

Empty strings can now be sorted using the base filter service
This commit is contained in:
Sean Engelhardt 2019-06-27 14:32:13 +02:00
parent 19a389cae6
commit 1aa41945c5

View File

@ -211,6 +211,14 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
return data.sort(this.sortFn); return data.sort(this.sortFn);
} }
/**
* Helper function to determine false-like values (if they are not boolean)
* @param property
*/
private isFalsy(property: any): boolean {
return property === null || property === undefined || property === 0 || property === '';
}
/** /**
* Recreates the sorting function. Is supposed to be called on init and * Recreates the sorting function. Is supposed to be called on init and
* every time the sorting (property, ascending/descending) or the language changes * every time the sorting (property, ascending/descending) or the language changes
@ -218,30 +226,29 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
protected updateSortedData(): void { protected updateSortedData(): void {
if (this.inputData) { if (this.inputData) {
const property = this.sortProperty as string; const property = this.sortProperty as string;
const intl = new Intl.Collator(this.translate.currentLang);
this.outputSubject.next( const intl = new Intl.Collator(this.translate.currentLang, {
numeric: true,
ignorePunctuation: true,
sensitivity: 'base'
});
this.inputData.sort((itemA, itemB) => { this.inputData.sort((itemA, itemB) => {
// always sort falsy values to the bottom
if (this.isFalsy(itemA[property]) && this.isFalsy(itemB[property])) {
return 0;
} else if (this.isFalsy(itemA[property])) {
return 1;
} else if (this.isFalsy(itemB[property])) {
return -1;
}
const firstProperty = this.ascending ? itemA[property] : itemB[property]; const firstProperty = this.ascending ? itemA[property] : itemB[property];
const secondProperty = this.ascending ? itemB[property] : itemA[property]; const secondProperty = this.ascending ? itemB[property] : itemA[property];
if (typeof firstProperty !== typeof secondProperty) {
// undefined/null items should always land at the end
if (!firstProperty) {
return 1;
} else if (!secondProperty) {
return -1;
} else {
throw new TypeError('sorting of items failed because of mismatched types');
}
} else {
if (
(firstProperty === null || firstProperty === undefined) &&
(secondProperty === null || secondProperty === undefined)
) {
return 1;
}
switch (typeof firstProperty) { switch (typeof firstProperty) {
case 'boolean': case 'boolean':
if (firstProperty === false && secondProperty === true) { if (!firstProperty && secondProperty) {
return -1; return -1;
} else { } else {
return 1; return 1;
@ -249,10 +256,15 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
case 'number': case 'number':
return firstProperty > secondProperty ? 1 : -1; return firstProperty > secondProperty ? 1 : -1;
case 'string': case 'string':
if (!firstProperty) { if (!!firstProperty && !secondProperty) {
return -1;
} else if (!firstProperty && !!secondProperty) {
return 1; return 1;
} } else if ((!secondProperty && !secondProperty) || firstProperty === secondProperty) {
return 0;
} else {
return intl.compare(firstProperty, secondProperty); return intl.compare(firstProperty, secondProperty);
}
case 'function': case 'function':
const a = firstProperty(); const a = firstProperty();
const b = secondProperty(); const b = secondProperty();
@ -268,9 +280,9 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
default: default:
return -1; return -1;
} }
} });
})
); this.outputSubject.next(this.inputData);
} }
} }
} }