DKowal
DKowal

Reputation: 37

Angular pipe sorting

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

Answers (2)

This is my solution for ordering in Angular with pipe.

+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

Heehaaw
Heehaaw

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

Related Questions