Skip to main content

Custom Pipes

Creating a custom pipe in Angular allows you to define a reusable transformation that can be applied within your templates. This is particularly useful when you need to perform a specific transformation on data in multiple places within your application that isn’t covered by Angular's built-in pipes.

Steps to Create a Custom Pipe

  1. Create Pipe Class: Generate a new pipe using the Angular CLI or create a class manually.

    • Using CLI: ng generate pipe my-custom-pipe

    • Manually:

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

      @Pipe({
      name: 'myCustomPipe'
      })
      export class MyCustomPipe implements PipeTransform {
      transform(value: any, ...args: any[]): any {
      // Transformation logic here
      }
      }
  2. Implement PipeTransform Interface: Your pipe class should implement the PipeTransform interface, which requires a transform method. This method takes an input value and returns a transformed value.

    transform(value: any, arg1: any, arg2: any): any {
    // Your transformation logic
    return transformedValue;
    }
  3. Add Logic to transform Method: Inside the transform method, add the logic for transforming the input value. You can also use additional arguments as needed.

  4. Decorate with @Pipe: The @Pipe decorator is used to define metadata for your pipe:

    • name: A string that represents the name you'll use within template expressions to invoke your pipe.
  5. Register the Pipe: Add your pipe to the declarations array of your Angular module.

    @NgModule({
    declarations: [
    // other components and pipes
    MyCustomPipe
    ],
    // ...
    })
    export class AppModule { }

Example of a Custom Pipe

Let’s say you want to create a custom pipe that appends a certain string to the end of the input value.

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

@Pipe({
name: 'appendString'
})
export class AppendStringPipe implements PipeTransform {
transform(value: string, appendString: string = ''): string {
return value + appendString;
}
}

// Usage in a component's template:
// {{ 'Hello' | appendString:' World!' }}
// Output: "Hello World!"

1. Filtering an Array

A custom pipe to filter an array based on a search term:

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

@Pipe({
name: 'filterArray'
})
export class FilterArrayPipe implements PipeTransform {
transform(items: any[], searchTerm: string): any[] {
if (!items || !searchTerm) {
return items;
}
return items.filter(item => item.toLowerCase().includes(searchTerm.toLowerCase()));
}
}

// Usage in template:
// <li *ngFor="let item of items | filterArray:searchText">{{ item }}</li>

2. Sorting an Array

A custom pipe for sorting an array of objects by a specific property:

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

@Pipe({
name: 'sortArray'
})
export class SortArrayPipe implements PipeTransform {
transform(array: any[], field: string): any[] {
if (!Array.isArray(array)) {
return;
}
array.sort((a, b) => (a[field] > b[field]) ? 1 : -1);
return array;
}
}

// Usage in template:
// <li *ngFor="let item of items | sortArray:'name'">{{ item.name }}</li>

3. Capitalizing Text

A simple pipe to capitalize the first letter of each word in a string:

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

@Pipe({
name: 'capitalize'
})
export class CapitalizePipe implements PipeTransform {
transform(value: string): string {
if (!value) return value;
return value.replace(/\b\w/g, first => first.toLocaleUpperCase());
}
}

// Usage in template:
// <div>{{ 'hello world' | capitalize }}</div>
// Output: "Hello World"

4. Truncating Text

A pipe to truncate text to a specified length:

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

@Pipe({
name: 'truncate'
})
export class TruncatePipe implements PipeTransform {
transform(value: string, limit: number = 40, completeWords: boolean = false, ellipsis: string = '...'): string {
if (completeWords) {
limit = value.substr(0, limit).lastIndexOf(' ');
}
return value.length > limit ? value.substr(0, limit) + ellipsis : value;
}
}

// Usage in template:
// <div>{{ longText | truncate:50:false }}</div>

5. Converting Markdown to HTML

A more complex pipe to convert Markdown text to HTML (requires a Markdown-to-HTML library):

import { Pipe, PipeTransform } from '@angular/core';
import * as marked from 'marked'; // Assuming 'marked' library is used

@Pipe({
name: 'markdown'
})
export class MarkdownPipe implements PipeTransform {
transform(value: string): string {
return value ? marked(value) : '';
}
}

// Usage in template:
// <div [innerHTML]="markdownText | markdown"></div>

Best Practices

  • Pure Pipes: By default, pipes are pure. A pure pipe only executes when it detects a pure change to the input (primitive value changes or object reference changes). It’s important for performance reasons.
  • Testing: Write unit tests for your custom pipes to ensure they behave as expected with various inputs.
  • Single Responsibility: A pipe should do one thing and do it well. If you find yourself adding too many unrelated features to a pipe, consider splitting it into multiple pipes.

Conclusion

Creating custom pipes in Angular is a straightforward process and immensely powerful for handling data transformations in your templates. By encapsulating transformation logic in reusable pipes, you maintain cleaner, more readable components and templates. Custom pipes enhance the modularity and maintainability of your Angular applications.