Создание своих pipes

Если нам потребуется некоторая предобработка при выводе данных, дополнительное форматирование, то мы можем для этой цели написать свои собственные pipes.

Классы pipes должны реализовать интерфейс PipeTransform

interface PipeTransform {
  transform(value: any, ...args: any[]): any
}

Метод transform должен преобразовать входное значение. Этот метод в качестве параметра принимает значение, к которому применяется pipe, а также опциональный набор параметров. А на выходе возвращается отформатированное значение. Поскольку первый параметр представляет тип any, а второй параметр - массив типа any, то соответственно мы можем передавать данные любых типов. И также можем возвращать объект любого типа.

Рассмотрим простейший пример. Допустим, нам надо выводить число, в котором разделителем между целой и дробной частью является запятая, а не точка. Для этого мы можем написать небольшой pipe. Для этого добавим в проект в папку src/app новый файл

format.pipe.ts:



Определим в этом файле следующий код:

import { Pipe, PipeTransform } from '@angular/core';
 
@Pipe({
    name: 'format'
})
export class FormatPipe implements PipeTransform {
  transform(value: number, args?: any): string {
 
    return value.toString().replace(".", ",");
  }
}

К кастомному pipe должен применяться декоратор Pipe. Этот декоратор определяет метаданные, в частности, название pipe, по которому он будет использоваться:

@Pipe({
    name: 'format'
})

Применим FormatPipe в коде компонента:

import { Component} from '@angular/core';
 
@Component({
    selector: 'my-app',
    template: `<div>Число до форматирования: {{x}}<br>Число после форматирования: {{x | format}}</div>`
})
export class AppComponent { 
 
    x: number = 15.45;
}

Но чтобы задействовать FormatPipe, его надо добавить в главном модуле приложения AppModule:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }   from './app.component';
import { FormatPipe} from './format.pipe';
 
@NgModule({
    imports:      [ BrowserModule],
    declarations: [ AppComponent, FormatPipe],
    bootstrap:    [ AppComponent ]
})
export class AppModule { }


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

Добавим еще один pipe, который будет принимать параметры. Пусть это будет класс, который из массива строк будет создавать строку, принимая начальный и конечный индексы для выборки данных из массива. Для этого добавим в проект новый файл join.pipe.ts, в котором определим следующее содержимое:

import { Pipe, PipeTransform } from '@angular/core';
 
@Pipe({
    name: 'join'
})
export class JoinPipe implements PipeTransform {
  transform(array: any, start?: any, end?: any): any {
    let result = array;
    if(start!==undefined){
        if(end!==undefined){
            result = array.slice(start, end);
        }
        else{
            result = array.slice(start, result.length);
        }
    }
    return result.join(", ");
  }
}

В метод transform класса JoinPipe первым параметром передается массив, второй необязательный параметр start представляет начальный индекс, с которого производится выборка, а третий параметр end - конечный индекс.

С помощью метода slice() получаем нужную часть массива, а с помощью метода join() соединяем массив в строку.

Применим JoinPipe:

import { Component} from '@angular/core';
 
@Component({
    selector: 'my-app',
    template: `<div>{{users | join}}</div>
               <div>{{users | join:1}}</div>
               <div>{{users | join:1:3}}</div>`
})
export class AppComponent { 
 
    users = ["Tom", "Alice", "Sam", "Kate", "Bob"];
}

Опять же подключим JoinPipe в модуле приложения:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }   from './app.component';
import { FormatPipe} from './format.pipe';
import { JoinPipe} from './join.pipe';
@NgModule({
    imports:      [ BrowserModule],
    declarations: [ AppComponent, FormatPipe, JoinPipe ],
    bootstrap:    [ AppComponent ]
})
export class AppModule { }

Результат работы: