Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OrderBy pipe issue

People also ask

Is there a sort pipe in angular?

The sort pipe takes 4 arguments:The results of the filter pipe, the direction of sorting i.e ascending or descending,the type of column to sort i.e string or numeric and also the column to be sorted. The default value of direction is “asc” and the default value of the column to sort when the component loads is “first”.

How angular pipes work?

You use data binding with a pipe to display values and respond to user actions. If the data is a primitive input value, such as String or Number , or an object reference as input, such as Date or Array , Angular executes the pipe whenever it detects a change for the input value or reference.

What is Pipe chaining in angular?

What Is Chaining Pipe? The chaining Pipe is used to perform the multiple operations within the single expression. This chaining operation will be chained using the pipe (I). In the following example, to display the birthday in the upper case- will need to use the inbuilt date-pipe and upper-case-pipe.


I modified @Thierry Templier's response so the pipe can sort custom objects in angular 4:

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name: "sort"
})
export class ArraySortPipe  implements PipeTransform {
  transform(array: any, field: string): any[] {
    if (!Array.isArray(array)) {
      return;
    }
    array.sort((a: any, b: any) => {
      if (a[field] < b[field]) {
        return -1;
      } else if (a[field] > b[field]) {
        return 1;
      } else {
        return 0;
      }
    });
    return array;
  }
}

And to use it:

*ngFor="let myObj of myArr | sort:'fieldName'"

Hopefully this helps someone.


Please see https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe for the full discussion. This quote is most relevant. Basically, for large scale apps that should be minified aggressively the filtering and sorting logic should move to the component itself.

"Some of us may not care to minify this aggressively. That's our choice. But the Angular product should not prevent someone else from minifying aggressively. Therefore, the Angular team decided that everything shipped in Angular will minify safely.

The Angular team and many experienced Angular developers strongly recommend that you move filtering and sorting logic into the component itself. The component can expose a filteredHeroes or sortedHeroes property and take control over when and how often to execute the supporting logic. Any capabilities that you would have put in a pipe and shared across the app can be written in a filtering/sorting service and injected into the component."


You could implement a custom pipe for this that leverages the sort method of arrays:

import { Pipe } from "angular2/core";

@Pipe({
  name: "sort"
})
export class ArraySortPipe {
  transform(array: Array<string>, args: string): Array<string> {
    array.sort((a: any, b: any) => {
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      } else {
        return 0;
      }
    });
    return array;
  }
}

And use then this pipe as described below. Don't forget to specify your pipe into the pipes attribute of the component:

@Component({
  (...)
  template: `
    <li *ngFor="list | sort"> (...) </li>
  `,
  pipes: [ ArraySortPipe ]
})
(...)

It's a simple sample for arrays with string values but you can have some advanced sorting processing (based on object attributes in the case of object array, based on sorting parameters, ...).

Here is a plunkr for this: https://plnkr.co/edit/WbzqDDOqN1oAhvqMkQRQ?p=preview.

Hope it helps you, Thierry


Updated OrderByPipe: fixed not sorting strings.

create a OrderByPipe class:

import { Pipe, PipeTransform } from "@angular/core";
@Pipe( {
name: 'orderBy'
} )
export class OrderByPipe implements PipeTransform {
transform( array: Array<any>, orderField: string, orderType: boolean ): Array<string> {
    array.sort( ( a: any, b: any ) => {
        let ae = a[ orderField ];
        let be = b[ orderField ];
        if ( ae == undefined && be == undefined ) return 0;
        if ( ae == undefined && be != undefined ) return orderType ? 1 : -1;
        if ( ae != undefined && be == undefined ) return orderType ? -1 : 1;
        if ( ae == be ) return 0;
        return orderType ? (ae.toString().toLowerCase() > be.toString().toLowerCase() ? -1 : 1) : (be.toString().toLowerCase() > ae.toString().toLowerCase() ? -1 : 1);
    } );
    return array;
  }
}

in your controller:

@Component({
pipes: [OrderByPipe]
})

or in your

 declarations: [OrderByPipe]

in your html:

<tr *ngFor="let obj of objects | orderBy : ObjFieldName: OrderByType">

ObjFieldName: object field name you want to sort;

OrderByType: boolean; true: descending order; false: ascending;