Заказать проект
Оставьте заявку для получения коммерческого предложения.
Заполните форму и мы вышлем Вам предложение в котором решим,
чем можем вам помочь.
Кастомные Pipes в Angular

Кастомные Pipes в Angular

16 Апреля 2019
Николай Гоцалюк
Frontend TeamLead
Николай Гоцалюк
следующая статья

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

Fri Apr 14 1976 00:00:00 GMT-0700 (Pacific Daylight Time)

В самом Angular для решения этого и подобных вопросов, есть  такой инструмент как Pipes. Название оправдывает принцип деятельности: мы забрасываем в “трубу” разные данные и на другом конце из нее вылетает то, что нам нужно.

Пример неформатированного вивода:

Ваш день рождения: {{ birthday }}

Пример форматированного вывода с использованием Pipes:

Ваш день рождения: {{ birthday | data }}

Уже готовых Pipes в Angular существует целый набор, подробно о котором можно узнать в документации.

Монтируем трубопровод

Конечно, готовые решения подходят далеко не всем и не всегда. В случае, когда нужный функционал не предусмотрен, “трубу” можно без затруднений создать самостоятельно. Давайте рассмотрим на конкретном примере.

Допустим у нас есть размер файла в байтах, а нужно реализовать вывод, который базируется на размере и приводит его к нужному префиксу Kb/Mb/Gb/Tb. Чтоб создать свой рipe, сначала создадим файл FileSizePipe.ts где задекларируем класс:

export class FileSizePipe  {}

Теперь задекларируем имя нашего pipe с помощью декоратора @Pipe:

import { Pipe } from '@angular/core';
@Pipe({
 name: 'filesize'
})
 export class FileSizePipe {}

С помощью этого имени теперь можно обращаться к нашему pipe из шаблонов компонентов, как в случае с датой:

<p> {{ file.size | filesize }} </p>

И, главное, не забываем подключить все в модуль  @NgModule в declaration:

// ...
import { FileSizePipe } from './filesize.pipe';
@NgModule({

 declarations: [
   //...
   FileSizePipe,
 ],
})
export class AppModule {}

Следующим шагом будет имплементация интерфейса PipeTransform:

import { Pipe, PipeTransform } from '@angular/core';
			 
@Pipe({ name: 'filesize' })
export class FileSizePipe implements PipeTransform {
 transform() {}
}

Если вы используете Angular CLI, все манипуляции, которые выложены выше, можно провести одной командой в консоле:

ng generate pipe FileSizePipe

И Angular CLI сделает все за вас. Все нужные надстройки к автогенерации находятся тут.

Далее вся магия заключается в методе transform(), который получает значение и будет возвращать уже  форматированое значение приемлемого для нас вида. Теперь давайте сразу добавим нашу логику:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
 name: 'filesize'
})
export class FileSizePipe implements PipeTransform {
 transform(value: any): string{
   let sizes = [' Bytes', ' KB', ' MB', ' GB', ' TB'];
   let l = 0, n = parseInt(value, 10) || 0;
   while(n >= 1024 && ++l)
     n = n/1024;
   return(n.toFixed(n >= 10 || l < 1 ? 0 : 1) + sizes[l]);
 }
}

Наконец применим именно наш pipe:

import {Component} from '@angular/core';
@Component({
 selector: 'app-root',
 template: '<p> {{ file.size | filesize }} </p>'
 })
export class AppComponent {
 file = {   size: 649233223 };
}

И посмотрим результат:

			 619 MB

Совершенствуем метод

Еще несколько слов о методе transform(). Если посмотреть на его структуру, можно заметить и другие аргументы кроме основного значения:

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

Рассмотрим их применение на нашем прежнем примере. Допустим, мы хотим повторить вывод  результата N раз. Тогда при обращении в шаблоне нужно передать второй параметр и это будет выглядеть так:

<p> {{ file.size | filesize:4 }} </p>

Ну и немного допишем наш метод:

transform(value: any, times:number):string{
let sizes = [' Bytes', ' KB', ' MB', ' GB', ' TB'];
let l = 0, n = parseInt(value, 10) || 0;
while(n >= 1024 && ++l)
   n = n/1024;
return (n.toFixed(n >= 10 || l < 1 ? 0 : 1) + sizes[l]+'. ').repeat(times);
}

Теперь в результате мы увидим: 619 MB. 619 MB. 619 MB. 619 MB.

Таким образом вы заметили, что в кастомизации pipes нет ничего сложного. Синтаксис достаточно простой и понятный. Создание своих “труб” может стать весьма занятным делом. А в дальнейшем свои pipes можно будет с легкостью переносить и использовать в других проектах.

Получайте больше вместе с Авиви!

Need help?

Ask a question.

Chat Now
Записаться На Консультацию
Записаться На Консультацию
Мы свяжемся
с вами
в течении
10 минут
laptop
Мы свяжемся с вами в течении 10 минут