Создание пользовательских пайпов

В Angular пайпы (pipes) предназначены для преобразования данных в шаблонах без изменения исходного объекта. Они позволяют выполнять фильтрацию, форматирование, преобразование значений и другие операции прямо в HTML. Помимо встроенных пайпов, таких как DatePipe, CurrencyPipe или UpperCasePipe, фреймворк поддерживает создание собственных пользовательских пайпов, что расширяет возможности приложения и повышает гибкость работы с данными.

Основы создания пайпов

Пайп в Angular реализуется как класс, который помечается декоратором @Pipe. Декоратор принимает объект с обязательным свойством name, которое определяет идентификатор пайпа для использования в шаблонах:

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

@Pipe({
  name: 'examplePipe'
})
export class ExamplePipe implements PipeTransform {
  transform(value: any, ...args: any[]): any {
    return value;
  }
}

Ключевые моменты:

  • Класс должен реализовывать интерфейс PipeTransform.
  • Метод transform является единственным обязательным методом и выполняет преобразование данных.
  • Параметр value — это исходное значение, переданное пайпу.
  • ...args — дополнительные аргументы, переданные через шаблон.

Пример использования в шаблоне:

<p>{{ 'angular' | examplePipe }}</p>

Пайпы с параметрами

Пайпы могут принимать дополнительные аргументы, которые позволяют динамически изменять поведение трансформации:

@Pipe({
  name: 'multiply'
})
export class MultiplyPipe implements PipeTransform {
  transform(value: number, factor: number = 1): number {
    return value * factor;
  }
}

Применение в шаблоне:

<p>{{ 5 | multiply:10 }}</p> <!-- Результат: 50 -->

Параметры передаются после двоеточия и могут быть любыми: числа, строки, булевы значения или даже объекты.

Чистые и нечистые пайпы

Angular различает чистые (pure) и нечистые (impure) пайпы:

  • Чистый пайп вычисляется только при изменении входных значений. По умолчанию все пайпы Angular являются чистыми (pure: true).
  • Нечистый пайп вызывается при каждом цикле обнаружения изменений, что полезно для массивов, объектов или данных, которые изменяются “по месту”.

Пример нечистого пайпа:

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

Нечистые пайпы нужно использовать осторожно, так как они могут негативно влиять на производительность приложения при большом количестве элементов.

Комплексные примеры

Форматирование дат с кастомной логикой:

@Pipe({
  name: 'customDate'
})
export class CustomDatePipe implements PipeTransform {
  transform(value: Date | string, format: string = 'dd/MM/yyyy'): string {
    const date = new Date(value);
    const day = String(date.getDate()).padStart(2, '0');
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const year = date.getFullYear();
    if (format === 'yyyy-MM-dd') {
      return `${year}-${month}-${day}`;
    }
    return `${day}/${month}/${year}`;
  }
}

Фильтрация массива объектов по полю:

@Pipe({
  name: 'filterByProperty'
})
export class FilterByPropertyPipe implements PipeTransform {
  transform(items: any[], property: string, value: any): any[] {
    if (!items || !property || value === undefined) return items;
    return items.filter(item => item[property] === value);
  }
}

Применение:

<li *ngFor="let user of users | filterByProperty:'role':'admin'">
  {{ user.name }}
</li>

Регистрация и использование

Пайп необходимо зарегистрировать в модуле приложения или в любом модуле, где предполагается его использование:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { MultiplyPipe } from './multiply.pipe';

@NgModule({
  declarations: [
    AppComponent,
    MultiplyPipe
  ],
  imports: [BrowserModule],
  bootstrap: [AppComponent]
})
export class AppModule { }

После этого пайп доступен в любом компоненте модуля и может применяться в шаблонах через синтаксис {{ value | pipeName }}.

Советы по производительности

  • Использовать чистые пайпы, когда данные неизменяемы.
  • Для больших массивов избегать нечистых пайпов, вместо этого лучше фильтровать и сортировать данные в компоненте.
  • Пайпы должны быть короткими и оптимизированными, чтобы не тормозить цикл обнаружения изменений.

Применение пайпов в реактивных формах и асинхронных данных

Пайпы хорошо интегрируются с RxJS и реактивными формами. Асинхронные пайпы (AsyncPipe) позволяют подписываться на Observable или Promise прямо в шаблоне:

<p>{{ data$ | async | customDate:'yyyy-MM-dd' }}</p>

Можно комбинировать пользовательские пайпы с AsyncPipe, создавая мощные цепочки обработки данных без дополнительного кода в компоненте.


Пользовательские пайпы в Angular обеспечивают чистый и удобный способ обработки данных в шаблонах, повышая читаемость кода и снижая дублирование логики. Правильное использование чистых и нечистых пайпов, а также параметров трансформации позволяет создавать гибкие и высокопроизводительные интерфейсы.