Angular orderBy pipe

Viewed 15677

I want to order my result by a property name but the following gives me an error:

*ngFor="let s of rslt| order by:wind_park">

what i get from back-end:

data = [
  { turbine_name: "Baynne ", wind_park: "Bayone" },
  { turbine_name: "Salstiegl ", wind_park: "Salzst" },
  { turbine_name: "Chradurga - SLL2", wind_park: "Chiarga" },
  { turbine_name: "Moilishte ", wind_park: "Mogihte" },
  { turbine_name: "Mogshte ", wind_park: "Mogshte" }
]

How can I order it and what's the best practice? Thank you all in advance.

5 Answers

You need to create your own OrderBy pipe to satisfy your needs, lodash is a cool library which has bunch of ready made functions which do the trick orderBy.

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

@Pipe({
 name: "orderBy"
})
export class OrderByPipe implements PipeTransform {
 transform(array: any, sortBy: string, order?: string): any[] {
 const sortOrder = order ? order : 'asc'; // setting default ascending order

  return orderBy(array, [sortBy], [sortOrder]);
  }
}

Usage in template

<div *ngFor="let w of data | orderBy: 'wind_park'">{{ w.wind_park}}</div> //default will sort ascending

for descending pass the desc in pipe

<div *ngFor="let w of data | orderBy: 'wind_park': 'desc'">{{ w.wind_park}}</div>

Make sure you declare pipe in your module

@NgModule({
  imports:  [ BrowserModule, FormsModule ],
  declarations: [ OrderByPipe ], // declare pipe here
  bootstrap:    [ AppComponent ]
 })

Working DEMO

Angular does not provide a pipe for sorting items. You have to implement it yourself. I think the best way to sort items is through a pipe. That is a simple example:

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;
  }
}

To use it:

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

Do it like this:

*ngFor="let s of rslt | order_by:'wind_park'">

Your Pipe:

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

@Pipe({
  name: 'order_by'
})

export class SortPipe implements PipeTransform {
  transform(value: any, propName: string) {

   return value.sort((a, b) => {
      if (a[propName] < b[propName]) {
        return -1;
      } else if (a[propName] === b[propName]) {
        return 0;
      } else if (a[propName] > b[propName]) {
        return 1;
      }
      // if(a[propName] > b[propName]) return 1
      // else return 1;
    });

  }
}

Working example: https://stackblitz.com/edit/angular-ivy-knency?file=src%2Fapp%2Fapp.component.ts

Screenshot of working example:

enter image description here

Try one of these

*ngFor="let s of rslt| orderBy:['wind_park']">

Please refer to No filter or orderBy Pipe in Angular discussion Or

Create your own orderBy Pipe like in this answer

If all these doesn't satisfy you, you can install lodash to your project and then create your own pipe as follow

import {Pipe, PipeTransform} from '@angular/core';
import * as _ from 'lodash'

@Pipe({
    name: 'orderBy'
})
export class OrderByPipe implements PipeTransform {

    transform(array: Array<any>, args?: any): any {
        return _.orderBy(array, ['field1', 'field2'], ['asc', 'desc']);
    }

}

and you can use it like

*ngFor="let s of rslt| orderBy:'wind_park'">

For this to work you need to import this to your module

@NgModule({
    ...,
    declarations: [OrderByPipe, ...],
    ...
})

Hope it helps.

Kamran Khatti answer totally works, but if you decided not to create custom pipe you can use angular build in keyvaluepipe, it accepts custom compare function as a paramter.

component.html

<div *ngFor="let title of data | keyvalue:customsort"> 
  {{title.key}} ----- {{title.value.turbine_name}}
</div>

component.ts

customsort = 
   ((a, b)=>{
     if(a.value[this.propName] === b.value[this.propName]){
       return 0
     }else if(a.value[this.propName] === null){
       return -1;
     }else if(b.value[this.propName] === null){
       return 1;
     }
    return a.value[this.propName].toString().localeCompare(b.value[this.propName].toString());
  });

Working Example

Related