How to generate a pipe in Angular

Generating Angular pipes enables you to create reusable data transformation logic for templates, providing clean and consistent formatting across your application. As the creator of CoreUI, a widely used open-source UI library, I’ve generated numerous Angular pipes for date formatting, text transformation, number formatting, and custom data processing in enterprise applications and component libraries. From my expertise, the most efficient approach is to use Angular CLI’s generate pipe command. This method creates the proper pipe structure, implements the PipeTransform interface, and generates test files while following Angular best practices for pipe development and performance optimization.

Use ng generate pipe command to create a new Angular pipe with proper structure and PipeTransform interface.

# Generate a basic pipe
ng generate pipe truncate
# or shortened
ng g p truncate

# Generate pipe in specific folder
ng generate pipe shared/pipes/currency-format

# Generate pipe without test file
ng generate pipe truncate --skip-tests

# Generate pipe in a specific module
ng generate pipe truncate --module=shared

# Generate pipe with flat structure (no separate folder)
ng generate pipe truncate --flat
// truncate.pipe.ts (basic generated file)
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'truncate'
})
export class TruncatePipe implements PipeTransform {
  transform(value: string, limit = 50, trail = '...'): string {
    if (!value) return '';

    return value.length > limit
      ? value.substring(0, limit) + trail
      : value;
  }
}
// Advanced pipe examples
import { Pipe, PipeTransform } from '@angular/core';

// 1. Time ago pipe
@Pipe({
  name: 'timeAgo'
})
export class TimeAgoPipe implements PipeTransform {
  transform(value: Date | string): string {
    if (!value) return '';

    const date = new Date(value);
    const now = new Date();
    const seconds = Math.floor((now.getTime() - date.getTime()) / 1000);

    const intervals = {
      year: 31536000,
      month: 2592000,
      week: 604800,
      day: 86400,
      hour: 3600,
      minute: 60
    };

    for (const [unit, secondsInUnit] of Object.entries(intervals)) {
      const interval = Math.floor(seconds / secondsInUnit);
      if (interval >= 1) {
        return `${interval} ${unit}${interval === 1 ? '' : 's'} ago`;
      }
    }

    return 'Just now';
  }
}

// 2. File size pipe
@Pipe({
  name: 'fileSize'
})
export class FileSizePipe implements PipeTransform {
  transform(bytes: number, decimals = 2): string {
    if (!bytes || bytes === 0) return '0 Bytes';

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];

    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
  }
}

// 3. Highlight search pipe
@Pipe({
  name: 'highlight'
})
export class HighlightPipe implements PipeTransform {
  transform(text: string, search: string, className = 'highlight'): string {
    if (!text || !search) return text;

    const regex = new RegExp(`(${search})`, 'gi');
    return text.replace(regex, `<span class="${className}">$1</span>`);
  }
}

// 4. Safe HTML pipe (for HTML content)
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

@Pipe({
  name: 'safeHtml'
})
export class SafeHtmlPipe implements PipeTransform {
  constructor(private sanitizer: DomSanitizer) {}

  transform(html: string): SafeHtml {
    return this.sanitizer.bypassSecurityTrustHtml(html);
  }
}

// 5. Filter pipe (for arrays)
@Pipe({
  name: 'filter',
  pure: false // Use with caution - can impact performance
})
export class FilterPipe implements PipeTransform {
  transform(items: any[], searchText: string, property?: string): any[] {
    if (!items || !searchText) return items;

    return items.filter(item => {
      const value = property ? item[property] : item;
      return value.toString().toLowerCase().includes(searchText.toLowerCase());
    });
  }
}

// 6. Sort pipe
@Pipe({
  name: 'sort',
  pure: false
})
export class SortPipe implements PipeTransform {
  transform(items: any[], property?: string, reverse = false): any[] {
    if (!items) return items;

    const sorted = items.sort((a, b) => {
      const valueA = property ? a[property] : a;
      const valueB = property ? b[property] : b;

      if (valueA < valueB) return reverse ? 1 : -1;
      if (valueA > valueB) return reverse ? -1 : 1;
      return 0;
    });

    return sorted;
  }
}
// Usage in component template
@Component({
  template: `
    <!-- Basic truncate pipe -->
    <p>{{ longText | truncate:30:'...' }}</p>

    <!-- Time ago pipe -->
    <span>Posted {{ post.createdAt | timeAgo }}</span>

    <!-- File size pipe -->
    <div>Size: {{ file.size | fileSize }}</div>

    <!-- Highlight pipe with safe HTML -->
    <div [innerHTML]="text | highlight:searchTerm | safeHtml"></div>

    <!-- Filter pipe -->
    <ul>
      <li *ngFor="let user of users | filter:searchText:'name'">
        {{ user.name }}
      </li>
    </ul>

    <!-- Sort pipe -->
    <div *ngFor="let item of items | sort:'name':true">
      {{ item.name }}
    </div>

    <!-- Chaining pipes -->
    <p>{{ user.bio | truncate:100 | titlecase }}</p>

    <!-- With parameters -->
    <span>{{ amount | currency:'USD':'symbol':'1.2-2' }}</span>
  `,
  styles: [`
    .highlight {
      background-color: yellow;
      font-weight: bold;
    }
  `]
})
export class MyComponent {
  longText = 'This is a very long text that needs to be truncated...';
  searchTerm = 'angular';
  users = [
    { name: 'John Doe', email: '[email protected]' },
    { name: 'Jane Smith', email: '[email protected]' }
  ];
}
// Don't forget to declare pipes in module
import { NgModule } from '@angular/core';
import { TruncatePipe } from './pipes/truncate.pipe';
import { TimeAgoPipe } from './pipes/time-ago.pipe';
import { FileSizePipe } from './pipes/file-size.pipe';

@NgModule({
  declarations: [
    TruncatePipe,
    TimeAgoPipe,
    FileSizePipe,
    // ... other pipes
  ],
  exports: [
    TruncatePipe,
    TimeAgoPipe,
    FileSizePipe,
    // ... other pipes
  ]
})
export class SharedModule {}

Angular CLI’s ng generate pipe command creates a pipe class that implements the PipeTransform interface with a required transform method. Pipes are pure by default (only execute when input changes), which optimizes performance. Use impure pipes (pure: false) sparingly as they execute on every change detection cycle. Pipes can accept multiple parameters and can be chained together. For security when dealing with HTML content, always use Angular’s DomSanitizer. Test pipes thoroughly with various input types and edge cases.

Best Practice Note:

This is the same approach we use for generating pipes in CoreUI Angular applications for consistent data formatting and transformation. Keep pipes pure for performance, handle null/undefined inputs gracefully, use descriptive names for pipe parameters, test with edge cases, and consider creating a shared pipes module for reusability across your application.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author