Перейти к содержанию

Пайпы

📅 30.09.2026

Обзор

Пайпы — особые операторы в выражениях шаблона Angular: они декларативно преобразуют данные прямо в шаблоне. Функцию преобразования объявляют один раз и затем используют в разных шаблонах. Пайпы Angular записывают вертикальной чертой (|) — по аналогии с конвейером Unix.

Синтаксис пайпов Angular отличается от обычного JavaScript, где вертикальная черта означает оператор побитового ИЛИ. Выражения шаблона Angular не поддерживают побитовые операторы.

Пример с несколькими встроенными пайпами Angular:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import {Component} from '@angular/core';
import {CurrencyPipe, DatePipe, TitleCasePipe} from '@angular/common';

@Component({
  selector: 'app-root',
  imports: [CurrencyPipe, DatePipe, TitleCasePipe],
  template: `
    <main>
      <!-- Transform the company name to title-case and
       transform the purchasedOn date to a locale-formatted string -->
      <h1>Purchases from {{ company | titlecase }} on {{ purchasedOn | date }}</h1>

      <!-- Transform the amount to a currency-formatted string -->
      <p>Total: {{ amount | currency }}</p>
    </main>
  `,
})
export class ShoppingCart {
  amount = 123.45;
  company = 'acme corporation';
  purchasedOn = '2024-07-08';
}

При отрисовке компонента Angular подбирает формат даты и валюты по локали пользователя. Для пользователя из США получится так:

1
2
3
4
<main>
  <h1>Purchases from Acme Corporation on Jul 8, 2024</h1>
  <p>Total: $123.45</p>
</main>

Подробнее о том, как Angular локализует значения, — в подробном руководстве по интернационализации.

Встроенные пайпы

В пакете @angular/common есть набор встроенных пайпов:

Имя Описание
AsyncPipe Читает значение из Promise или RxJS Observable.
CurrencyPipe Преобразует число в строку валюты по правилам локали.
DatePipe Форматирует значение Date по правилам локали.
DecimalPipe Преобразует число в строку с десятичной точкой по правилам локали.
I18nPluralPipe Сопоставляет значение со строкой, которая ставит его во множественное число по правилам локали.
I18nSelectPipe Сопоставляет ключ с пользовательским селектором, который возвращает нужное значение.
JsonPipe Преобразует объект в строку через JSON.stringify, предназначен для отладки.
KeyValuePipe Преобразует Object или Map в массив пар «ключ — значение».
LowerCasePipe Переводит текст в нижний регистр.
PercentPipe Преобразует число в строку процентов по правилам локали.
SlicePipe Создаёт новый Array или String с подмножеством (срезом) элементов.
TitleCasePipe Переводит текст в регистр заголовка.
UpperCasePipe Переводит текст в верхний регистр.

Использование пайпов

Оператор пайпа Angular — вертикальная черта (|) внутри выражения шаблона. Это бинарный оператор: левый операнд — значение, которое передаётся функции преобразования, правый — имя пайпа и дополнительные аргументы (о них ниже).

1
<p>Total: {{ amount | currency }}</p>

В этом примере значение amount передаётся в CurrencyPipe, имя пайпа — currency. Затем отрисовывается валюта по умолчанию для локали пользователя.

Несколько пайпов в одном выражении

К одному значению можно применить несколько преобразований, поставив несколько операторов пайпа. Angular выполняет пайпы слева направо.

В примере ниже пайпы вместе показывают локализованную дату в верхнем регистре:

1
<p>The event will occur on {{ scheduledOn | date | uppercase }}.</p>

Передача параметров пайпам

Некоторые пайпы принимают параметры, которые настраивают преобразование. Параметр указывают после имени пайпа через двоеточие (:) и значение параметра.

Например, DatePipe принимает параметры, чтобы отформатировать дату определённым образом.

1
<p>The event will occur at {{ scheduledOn | date: 'hh:mm' }}.</p>

Некоторые пайпы принимают несколько параметров. Дополнительные значения разделяют двоеточием (:).

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

1
<p>The event will occur at {{ scheduledOn | date: 'hh:mm' : 'UTC' }}.</p>

Как работают пайпы

По сути пайпы — функции: они принимают входное значение и возвращают преобразованное.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import {Component} from '@angular/core';
import {CurrencyPipe} from '@angular/common';

@Component({
  selector: 'app-root',
  imports: [CurrencyPipe],
  template: `
    <main>
      <p>Total: {{ amount | currency }}</p>
    </main>
  `,
})
export class AppComponent {
  amount = 123.45;
}

В этом примере:

  1. CurrencyPipe импортируется из @angular/common
  2. CurrencyPipe добавляется в массив imports
  3. Данные amount передаются пайпу currency

Приоритет оператора пайпа

Приоритет оператора пайпа ниже, чем у других бинарных операторов, включая +, -, *, /, %, &&, || и ??.

1
2
<!-- firstName and lastName are concatenated before the result is passed to the uppercase pipe -->
{{ firstName + lastName | uppercase }}

Приоритет оператора пайпа выше, чем у условного (тернарного) оператора.

1
{{ (isAdmin ? 'Access granted' : 'Access denied') | uppercase }}

Если то же выражение записать без скобок:

1
{{ isAdmin ? 'Access granted' : 'Access denied' | uppercase }}

Оно будет разобрано так:

1
{{ isAdmin ? 'Access granted' : ('Access denied' | uppercase) }}

Если приоритет операторов может быть неоднозначным, ставьте в выражениях скобки.

Обнаружение изменений и пайпы

По умолчанию все пайпы считаются pure: они выполняются только когда меняется примитивное входное значение (например, String, Number, Boolean или Symbol) или ссылка на объект (например, Array, Object, Function или Date). Чистые пайпы выгодны по производительности: Angular не вызывает функцию преобразования, если переданное значение не изменилось.

Поэтому мутации свойств объекта или элементов массива не обнаруживаются, пока всю ссылку на объект или массив не заменят другим экземпляром. Если нужно обнаружение изменений такого уровня, смотрите обнаружение изменений внутри массивов и объектов.

Создание собственных пайпов

Собственный пайп задают классом TypeScript с декоратором @Pipe. У пайпа должно быть две вещи:

  • Имя, указанное в декораторе пайпа
  • Метод с именем transform, который выполняет преобразование значения.

Класс TypeScript дополнительно должен реализовать интерфейс PipeTransform, чтобы удовлетворять сигнатуре типа пайпа.

Пример собственного пайпа, который переводит строки в kebab-case:

kebab-case.pipe.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
  name: 'kebabCase',
})
export class KebabCasePipe implements PipeTransform {
  transform(value: string): string {
    return value.toLowerCase().replace(/ /g, '-');
  }
}

Декоратор @Pipe

При создании собственного пайпа импортируйте Pipe из пакета @angular/core и повесьте его декоратором на класс TypeScript.

1
2
3
4
5
6
import {Pipe} from '@angular/core';

@Pipe({
  name: 'myCustomTransformation',
})
export class MyCustomTransformationPipe {}

Декоратору @Pipe нужен name: он задаёт, как пайп используется в шаблоне.

Соглашение об именах собственных пайпов

Соглашение об именах собственных пайпов состоит из двух правил:

  • name — рекомендуется camelCase. Дефисы не используйте.
  • class name — вариант name в PascalCase с суффиксом Pipe в конце

Реализация интерфейса PipeTransform

Помимо декоратора @Pipe, собственные пайпы всегда должны реализовать интерфейс PipeTransform из @angular/core.

1
2
3
4
5
6
import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
  name: 'myCustomTransformation',
})
export class MyCustomTransformationPipe implements PipeTransform {}

Реализация этого интерфейса гарантирует, что у класса пайпа правильная структура.

Преобразование значения пайпа

Каждое преобразование вызывает метод transform: первый параметр — передаваемое значение, возвращаемое значение — результат преобразования.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
  name: 'myCustomTransformation',
})
export class MyCustomTransformationPipe implements PipeTransform {
  transform(value: string): string {
    return `My custom transformation of ${value}.`;
  }
}

Параметры собственного пайпа

Параметры преобразования добавляют дополнительными параметрами метода transform:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
  name: 'myCustomTransformation',
})
export class MyCustomTransformationPipe implements PipeTransform {
  transform(value: string, format: string): string {
    let msg = `My custom transformation of ${value}.`;

    if (format === 'uppercase') {
      return msg.toUpperCase();
    } else {
      return msg;
    }
  }
}

Обнаружение изменений внутри массивов и объектов

Чтобы пайп обнаруживал изменения внутри массивов или объектов, его помечают нечистой функцией: флаг pure со значением false.

Не создавайте нечистые пайпы без крайней необходимости: при неосторожном использовании они сильно бьют по производительности.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
  name: 'joinNamesImpure',
  pure: false,
})
export class JoinNamesImpurePipe implements PipeTransform {
  transform(names: string[]): string {
    return names.join();
  }
}

Разработчики Angular часто добавляют Impure в name пайпа и в имя класса, чтобы предупредить коллег о возможной потере производительности.

Логика пайпа вне шаблонов

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

Вынесите логику из собственных пайпов

Когда создаёте собственный пайп, вынесите преобразование в отдельную функцию. Метод transform() пайпа пусть делегирует этой функции, а саму функцию импортируйте напрямую везде, где она ещё нужна.

kebab-case.ts

1
2
3
export function toKebabCase(value: string): string {
  return value.toLowerCase().replace(/ /g, '-');
}

kebab-case.pipe.ts

1
2
3
4
5
6
7
8
9
import {Pipe, PipeTransform} from '@angular/core';
import {toKebabCase} from './kebab-case';

@Pipe({name: 'kebabCase'})
export class KebabCasePipe implements PipeTransform {
  transform(value: string): string {
    return toKebabCase(value);
  }
}

formatter.service.ts

1
2
3
4
5
6
7
8
9
import {Service} from '@angular/core';
import {toKebabCase} from './kebab-case';

@Service()
export class FormatterService {
  formatSlug(title: string): string {
    return toKebabCase(title);
  }
}

formatter.service.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import {Service} from '@angular/core';
import {KebabCasePipe} from './kebab-case.pipe';

@Service()
export class FormatterService {
  // Avoid injecting the pipe class into services or other classes.
  private kebabCasePipe = inject(KebabCasePipe);

  formatSlug(title: string): string {
    return this.kebabCasePipe.transform(title);
  }
}

Функции форматирования вместо встроенных пайпов

У каждого встроенного пайпа Angular, который учитывает локаль, есть соответствующая отдельная функция форматирования, экспортируемая из @angular/common. Используйте эти функции вместо внедрения класса пайпа.

Пайп Отдельная функция
DatePipe formatDate
CurrencyPipe formatCurrency
DecimalPipe formatNumber
PercentPipe formatPercent
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import {Service, LOCALE_ID, inject} from '@angular/core';
import {formatNumber} from '@angular/common';

@Service()
export class PriceService {
  private locale = inject(LOCALE_ID);

  format(value: number) {
    return formatNumber(value, this.locale, '1.2-2');
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import {Service} from '@angular/core';
import {DecimalPipe} from '@angular/common';

@Service()
export class PriceService {
  private decimalPipe = inject(DecimalPipe);

  format(value: number) {
    return this.decimalPipe.transform(value, '1.2-2');
  }
}

Источник: https://angular.dev/guide/templates/pipes

Комментарии