The Pipe implementation
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'orderBy',
pure: false
})
export class OrderBy implements PipeTransform {
value:string[] =[];
static _orderByComparator(a:any, b:any):number{
if(a === null || typeof a === 'undefined') a = 0;
if(b === null || typeof b === 'undefined') b = 0;
if((isNaN(parseFloat(a)) || !isFinite(a)) || (isNaN(parseFloat(b)) || !isFinite(b))){
//Isn't a number so lowercase the string to properly compare
if(a.toLowerCase() < b.toLowerCase()) return -1;
if(a.toLowerCase() > b.toLowerCase()) return 1;
}else{
//Parse strings as numbers to compare properly
if(parseFloat(a) < parseFloat(b)) return -1;
if(parseFloat(a) > parseFloat(b)) return 1;
}
return 0; //equal each other
}
transform(input:any, config:string = '+'): any{
//make a copy of the input's reference
this.value = [...input];
let value = this.value;
if(!Array.isArray(value)) return value;
if(!Array.isArray(config) || (Array.isArray(config) && config.length === 1)){
let propertyToCheck:string = !Array.isArray(config) ? config : config[0];
let desc = propertyToCheck.substr(0, 1) === '-';
//Basic array
if(!propertyToCheck || propertyToCheck === '-' || propertyToCheck === '+'){
return !desc ? value.sort() : value.sort().reverse();
}else {
let property:string = propertyToCheck.substr(0, 1) === '+' || propertyToCheck.substr(0, 1) === '-'
? propertyToCheck.substr(1)
: propertyToCheck;
return value.sort(function(a:any,b:any){
return !desc
? OrderBy._orderByComparator(a[property], b[property])
: -OrderBy._orderByComparator(a[property], b[property]);
});
}
} else {
//Loop over property of the array in order and sort
return value.sort(function(a:any,b:any){
for(let i:number = 0; i < config.length; i++){
let desc = config[i].substr(0, 1) === '-';
let property = config[i].substr(0, 1) === '+' || config[i].substr(0, 1) === '-'
? config[i].substr(1)
: config[i];
let comparison = !desc
? OrderBy._orderByComparator(a[property], b[property])
: -OrderBy._orderByComparator(a[property], b[property]);
//Don't return 0 yet in case of needing to sort by next property
if(comparison !== 0) return comparison;
}
return 0; //equal each other
});
}
}
}
How to use the pipe in the HTML - order ascending by first name
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users | orderBy : ['firstName']>
<td>{{user.firstName}}</td>
<td>{{user.lastName}}</td>
<td>{{user.age}}</td>
</tr>
</tbody>
</table>
How to use the pipe in the HTML - order descending by first name
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users | orderBy : ['-firstName']>
<td>{{user.firstName}}</td>
<td>{{user.lastName}}</td>
<td>{{user.age}}</td>
</tr>
</tbody>
</table>