Reputation: 37
According to this question -> Ascending and Descending Sort in Angular 4
I've made the same pipe, but it can't sort numbers naturally. I mean 2 is > then 11.
How can this pipe be modified to sort both string and numbers?
@Pipe({
name: 'orderBy'
})
export class OrderByPipe implements PipeTransform {
transform(records: Array<any>, args?: any): any {
if (records && records.length > 0) {
return records.sort(function (a, b) {
if (a[args.property] < b[args.property]) {
return -1 * args.direction;
} else if (a[args.property] > b[args.property]) {
return 1 * args.direction;
} else {
return 0;
}
});
}
}
}
Upvotes: 0
Views: 1299
Reputation: 299
+Extra feature: Ascending and Descending with the third parameter.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'orderBy'
})
export class OrderByPipe implements PipeTransform {
transform(value: any[], key: string, dir: number = 1): any {
if (!value || !key) {
return value;
}
value.sort( (a, b) => {
return ('' + a[key]).localeCompare( ('' + b[key]) ) * dir;
});
return value;
}
}
I always cast values to a string, because the comparing is easiest.
Upvotes: 1
Reputation: 2847
That's because you are sorting the values as strings - lexicographically. The input for your pipe seems to be of type Array<{ [propertyName: string]: [value: string] }>
.
Either make sure that the input property values are numbers or convert the values to number
before comparing.
In case you need to sort based on the type of the data that came to your pipe, you can use something like this:
@Pipe({
name: 'orderBy'
})
export class OrderByPipe implements PipeTransform {
transform(records: Array<any>, args?: any): any {
if (records && records.length > 0) {
return records.sort(
(a, b) => args.direction * (
typeof a[args.property] === 'number'
? (a[args.property] - b[args.property])
: a[args.property] > b[args.property] ? 1 : -1)
);
}
}
}
Hope this helps a little :-)
Upvotes: 0