Learn how to use the orderBy pipe to manipulate data in templates to display them in the format we want.
Angular is a component-based framework that lets us create interactive web frontends for users by composing components together. In addition to components, we can create pipes that let us manipulate data in templates to display them in the format we want.
In this article, we’ll look at how to add an orderBy pipe into our app and use it in our template.
We can create our own pipes to transform data in our templates before displaying them.
To create the files for the pipe and register the pipe in our Angular app module, we use the ng g
command that comes with Angular CLI.
In this example, we will create a pipe that converts strings to lowercase before displaying them.
To start, we run:
ng generate pipe lowerCase
to create the lowerCase
pipe.
This will create the files and register them in the Angular app module so we can make changes to the pipe file and use it right away.
In app.module.ts
, we should see something like:
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { LowerCasePipe } from "./lower-case.pipe";
@NgModule({
declarations: [AppComponent, LowerCasePipe],
imports: [BrowserModule, AppRoutingModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
If we see LowerCasePipe
in declarations
, that means we can use it in our template in components that are registered in AppModule
.
We should have the lower-case.pipe.ts
file in the app
folder after running the command. In it, we write:
import { Pipe, PipeTransform } from "@angular/core";
@Pipe({
name: "lowerCase",
})
export class LowerCasePipe implements PipeTransform {
transform(value: string, ...args: unknown[]): unknown {
return value.toLowerCase();
}
}
We added the transform
method into the LowerCasePipe
class. It implements the PipeTransform
TypeScript interface, which requires the transform
method to be included.
The transform
method takes the value
, which is the value passed from the template to the pipe. We set its type to a string since we expect a string argument to be passed in.
It returns the result that we want to render in the template. In this case, we want to display the string in all lowercase. Therefore, we return the lowercase version of value by calling toLowerCase
.
Then in app.component.html
, we can use the lowerCase
pipe we just created.
In app.component.html
, we write:
<p>{{ "HELLO WORLD" | lowerCase }}</p>
to render the "HELLO WORLD"
string in all lowercase by applying the lowerCase
we just created.
We use the name
property value in the object we called the Pipe
decorator with as the pipe name in the template.
Pipes can be applied to values other than strings. We can apply pipes to any kind of value.
One kind of thing we commonly do is to order by items in an array before we display them. To do this, we can create a pipe. Pipes can take arguments, so we can sort array items in the way we want before we display the items.
To create a pipe that can sort arrays before we display the items, we use the JavaScript array sort
method. The sort
method takes a function that compares the two items being iterated through
as the arguments. sort
makes a copy of the array it called, sorts the copied array, and then returns the sorted copied array.
We can call these two parameters a
and b
.
For instance, we write:
const sorted = array.sort((a, b) => {
//...
});
to call sort
on the array
array with a function that takes items a
and b
and compares them.
a
and b
are items in the array
array that we are comparing.
If we compare the a
and b
items and return a number bigger than 0 in the sort
callback, then we sort a
after b
.
If we compare them and return a number less than 0 in the sort
callback, then we sort a
before b
.
And if we return 0 in the sort
callback, then we keep the original order of a
and b
.
For instance, if we write:
const array = [1, 5, 4, 2, 3];
const sorted = array.sort((a, b) => {
return a - b;
});
console.log(sorted);
Then sorted
is [1, 2, 3, 4, 5]
since we order a
before b
if a
is less than b
.
And if we write:
const array = [1, 5, 4, 2, 3];
const sorted = array.sort((a, b) => {
return b - a;
});
console.log(sorted);
Then sorted
is [5, 4, 3, 2, 1]
since we order b
before a
if b
is bigger than a
.
And if we write:
const array = [1, 5, 4, 2, 3];
const sorted = array.sort((a, b) => {
return 0;
});
console.log(sorted);
Then sorted
is [1, 5, 4, 2, 3]
since we keep the same order as the array.
With this information, we can make a pipe that orders the values we want.
To start, we create the orderBy
pipe by running:
ng generate pipe orderBy
Then in app.module.ts
, we see something like:
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { OrderByPipe } from "./order-by.pipe";
@NgModule({
declarations: [AppComponent, OrderByPipe],
imports: [BrowserModule, AppRoutingModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
The OrderByPipe
is in the array we set as the value of the declarations
property, so it’s registered in the AppModule
.
The order-by.pipe.ts
file should be created. And we can modify that to sort the values we want before displaying them.
Next, we create the Person
interface since we want our pipe to sort these objects. To create the person.ts
file, we run:
ng generate interface Person
In it, we write:
export interface Person {
name: string;
age: number;
}
to add the name
and age
properties into our TypeScript interface.
Now we can work on our pipe.
In order-by.pipe.ts
, we write:
import { Pipe, PipeTransform } from "@angular/core";
import { Person } from "./person";
@Pipe({
name: "orderBy",
})
export class OrderByPipe implements PipeTransform {
transform(value: Person[], order: "asc" | "desc" = "asc"): Person[] {
return value.sort((a, b) => {
if (order === "asc") {
return a.age - b.age;
} else if (order === "desc") {
return b.age - a.age;
}
return 0;
});
}
}
to add the transform
method.
It takes the value
parameter, which is an array of Person
objects. Person
is the interface we created earlier.
order
is an argument for the pipe that lets us specify whether to sort by asc
(ascending order) or desc
(descending order). In it, we call
value.sort
with a callback that checks the order
direction.
If it’s asc
, then we sort by age
in ascending order. If it’s desc
, then we sort by age
in descending order.
Otherwise, we return the array with the same items as value
in the same order.
We set the type of value
to Person[]
so only an array of Person
objects is accepted.
order
has type "asc" | "desc"
with the default value being "asc"
so only "asc"
or "desc"
can be values of
order
.
And the return type of the transform
method is Person[]
since sort
returns an array with the objects in value
sorted. We
need the types to avoid TypeScript type errors.
Next, we can add some Person
objects in AppComponent
and display them in a sorted manner. To do this, we write:
import { Component } from "@angular/core";
import { Person } from "./person";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
persons: Person[] = [
{ name: "Joe", age: 50 },
{ name: "Jane", age: 10 },
{ name: "Mary", age: 30 },
{ name: "Alex", age: 23 },
{ name: "Steve", age: 68 },
{ name: "Paul", age: 91 },
];
orderBy: "asc" | "desc" = "asc";
}
in app.component.ts
.
We have an array of Person
objects set as the value of the persons
instance variable.
Also, we have the orderBy
instance variable initially set to "asc"
.
Then in app.component.html
, we write:
<button (click)="orderBy = orderBy === 'asc' ? 'desc' : 'asc'">
Toggle Sort
</button>
<ul>
<li *ngFor="let p of persons | orderBy: orderBy">
{{ p.name }} - {{ p.age }}
</li>
</ul>
to add a button that lets us toggle the value of orderBy
between "asc"
and "desc"
.
And then we render the items in persons
after they’re sorted by the orderBy
pipe we just created.
The orderBy
after the colon is the orderBy
instance variable in AppComponent
which we set as the argument of the orderBy
pipe.
As a result, we should see the items displayed in the list initially sorted by their age
values in ascending order. Then when we click Toggle Sort, we see the sort order reversed so the age
values are sorted in descending order.
In addition to components, we can create pipes in Angular that let us manipulate data in templates to display them in the format we want.
We can create our own pipe that sorts values in the order we want before we display them by using the array sort
method. The sort
method makes a copy of the array, sorts it and then returns
the sorted array so the original array isn’t affected.
John Au-Yeung is a frontend developer with 6+ years of experience. He is an avid blogger (visit his site at https://thewebdev.info/) and the author of Vue.js 3 By Example.