Angular 2
Tubería
Buscar..
Introducción
El tubo |
el carácter se utiliza para aplicar tuberías en Angular 2. Las tuberías son muy similares a los filtros en AngularJS, ya que ambas ayudan a transformar los datos en un formato específico.
Parámetros
Función / Parámetro | Explicación |
---|---|
@Pipe ({nombre, puro}) | Metadatos para tubería, debe preceder inmediatamente a la clase de tubería. |
nombre: cadena | lo que usarás dentro de la plantilla |
puro: booleano | el valor predeterminado es verdadero, marque esto como falso para que su tubería sea reevaluada con más frecuencia |
transformar (valor, args []?) | La función que se llama a transformar los valores en la plantilla. |
valor: cualquiera | El valor que quieres transformar. |
Args: cualquiera [] | Los argumentos que puede necesitar incluir en su transformación. Marque args opcionales con el? operador como tal transformar (valor, arg1, arg2?) |
Observaciones
Este tema trata sobre Angular2 Pipes , un mecanismo para transformar y formatear datos dentro de plantillas HTML en una aplicación Angular2.
Tuberías de encadenamiento
Las tuberías pueden estar encadenadas.
<p>Today is {{ today | date:'fullDate' | uppercase}}.</p>
Tubos personalizados
my.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'myPipe'})
export class MyPipe implements PipeTransform {
transform(value:any, args?: any):string {
let transformedValue = value; // implement your transformation logic here
return transformedValue;
}
}
my.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-component',
template: `{{ value | myPipe }}`
})
export class MyComponent {
public value:any;
}
my.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MyComponent } from './my.component';
import { MyPipe } from './my.pipe';
@NgModule({
imports: [
BrowserModule,
],
declarations: [
MyComponent,
MyPipe
],
})
export class MyModule { }
Tubos incorporados
Angular2 viene con algunos tubos integrados:
Tubo | Uso | Ejemplo |
---|---|---|
DatePipe | date | {{ dateObj | date }} // output is 'Jun 15, 2015' |
UpperCasePipe | uppercase | {{ value | uppercase }} // output is 'SOMETEXT' |
LowerCasePipe | lowercase | {{ value | lowercase }} // output is 'sometext' |
CurrencyPipe | currency | {{ 31.00 | currency:'USD':true }} // output is '$31' |
PercentPipe | percent | {{ 0.03 | percent }} //output is %3 |
Hay otros. Busque aquí su documentación.
Ejemplo
hotel-booking.component.ts
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'hotel-reservation',
templateUrl: './hotel-reservation.template.html'
})
export class HotelReservationComponent {
public fName: string = 'Joe';
public lName: string = 'SCHMO';
public reservationMade: string = '2016-06-22T07:18-08:00'
public reservationFor: string = '2025-11-14';
public cost: number = 99.99;
}
hotel-reservation.template.html
<div>
<h1>Welcome back {{fName | uppercase}} {{lName | lowercase}}</h1>
<p>
On {reservationMade | date} at {reservationMade | date:'shortTime'} you
reserved room 205 for {reservationDate | date} for a total cost of
{cost | currency}.
</p>
</div>
Salida
Welcome back JOE schmo
On Jun 26, 2016 at 7:18 you reserved room 205 for Nov 14, 2025 for a total cost of
$99.99.
Depuración Con JsonPipe
El JsonPipe se puede usar para depurar el estado de cualquier interno dado.
Código
@Component({
selector: 'json-example',
template: `<div>
<p>Without JSON pipe:</p>
<pre>{{object}}</pre>
<p>With JSON pipe:</p>
<pre>{{object | json}}</pre>
</div>`
})
export class JsonPipeExample {
object: Object = {foo: 'bar', baz: 'qux', nested: {xyz: 3, numbers: [1, 2, 3, 4, 5]}};
}
Salida
Without JSON Pipe:
object
With JSON pipe:
{object:{foo: 'bar', baz: 'qux', nested: {xyz: 3, numbers: [1, 2, 3, 4, 5]}}
Tubería personalizada disponible a nivel mundial
Para hacer que una tubería personalizada esté disponible en toda la aplicación, Durante la aplicación bootstrap, extienda PLATFORM_PIPES.
import { bootstrap } from '@angular/platform-browser-dynamic';
import { provide, PLATFORM_PIPES } from '@angular/core';
import { AppComponent } from './app.component';
import { MyPipe } from './my.pipe'; // your custom pipe
bootstrap(AppComponent, [
provide(PLATFORM_PIPES, {
useValue: [
MyPipe
],
multi: true
})
]);
Tutorial aquí: https://scotch.io/tutorials/create-a-globally-available-custom-pipe-in-angular-2
Creación de tubería personalizada
app / pipes.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'truthy'})
export class Truthy implements PipeTransform {
transform(value: any, truthy: string, falsey: string): any {
if (typeof value === 'boolean'){return value ? truthy : falsey;}
else return value
}
}
app / my-component.component.ts
import { Truthy} from './pipes.pipe';
@Component({
selector: 'my-component',
template: `
<p>{{value | truthy:'enabled':'disabled' }}</p>
`,
pipes: [Truthy]
})
export class MyComponent{ }
Desenvolver valores asíncronos con una tubería asíncrona
import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
@Component({
selector: 'async-stuff',
template: `
<h1>Hello, {{ name | async }}</h1>
Your Friends are:
<ul>
<li *ngFor="let friend of friends | async">
{{friend}}
</li>
</ul>
`
})
class AsyncStuffComponent {
name = Promise.resolve('Misko');
friends = Observable.of(['Igor']);
}
Se convierte en
<h1>Hello, Misko</h1>
Your Friends are:
<ul>
<li>
Igor
</li>
</ul>
Extendiendo una tubería existente
import { Pipe, PipeTransform } from '@angular/core';
import { DatePipe } from '@angular/common'
@Pipe({name: 'ifDate'})
export class IfDate implements PipeTransform {
private datePipe: DatePipe = new DatePipe();
transform(value: any, pattern?:string) : any {
if (typeof value === 'number') {return value}
try {
return this.datePipe.transform(value, pattern)
} catch(err) {
return value
}
}
}
Tubos de estado
Angular 2 ofrece dos tipos diferentes de tuberías: sin estado y con estado. Las tuberías son sin estado por defecto. Sin embargo, podemos implementar tuberías con estado estableciendo la propiedad pure
en false
. Como puede ver en la sección de parámetros, puede especificar un name
y declarar si la tubería debe ser pura o no, es decir, sin estado o sin estado. Mientras que los datos fluyen a través de una tubería sin estado (que es una función pura) que no recuerda nada, los datos pueden ser gestionados y recordados por tuberías con estado. Un buen ejemplo de una tubería con estado es el AsyncPipe
proporcionado por Angular 2.
Importante
Observe que la mayoría de las tuberías deben caer en la categoría de tuberías sin estado. Esto es importante por razones de rendimiento, ya que Angular puede optimizar tuberías sin estado para el detector de cambios. Así que use las tuberías con estado con cautela. En general, la optimización de tuberías en Angular 2 tiene una mayor mejora de rendimiento sobre los filtros en Angular 1.x. En Angular 1, el ciclo de resumen siempre tuvo que volver a ejecutar todos los filtros aunque los datos no hayan cambiado en absoluto. En Angular 2, una vez que se ha calculado el valor de una tubería, el detector de cambios sabe que no debe volver a ejecutar esta tubería a menos que cambie la entrada.
Implementación de una tubería con estado.
import {Pipe, PipeTransform, OnDestroy} from '@angular/core';
@Pipe({
name: 'countdown',
pure: false
})
export class CountdownPipe implements PipeTransform, OnDestroy {
private interval: any;
private remainingTime: number;
transform(value: number, interval: number = 1000): number {
if (!parseInt(value, 10)) {
return null;
}
if (typeof this.remainingTime !== 'number') {
this.remainingTime = parseInt(value, 10);
}
if (!this.interval) {
this.interval = setInterval(() => {
this.remainingTime--;
if (this.remainingTime <= 0) {
this.remainingTime = 0;
clearInterval(this.interval);
delete this.interval;
}
}, interval);
}
return this.remainingTime;
}
ngOnDestroy(): void {
if (this.interval) {
clearInterval(this.interval);
}
}
}
A continuación, puede utilizar la tubería como de costumbre:
{{ 1000 | countdown:50 }}
{{ 300 | countdown }}
Es importante que su tubería también implemente la interfaz OnDestroy
para que pueda limpiar una vez que se destruya su tubería. En el ejemplo anterior, es necesario borrar el intervalo para evitar pérdidas de memoria.
Tubo dinámico
Escenario de caso de uso: una vista de tabla consta de diferentes columnas con diferentes formatos de datos que deben transformarse con diferentes canalizaciones.
table.component.ts
... import { DYNAMIC_PIPES } from '../pipes/dynamic.pipe.ts'; @Component({ ... pipes: [DYNAMIC_PIPES] }) export class TableComponent { ... // pipes to be used for each column table.pipes = [ null, null, null, 'humanizeDate', 'statusFromBoolean' ], table.header = [ 'id', 'title', 'url', 'created', 'status' ], table.rows = [ [ 1, 'Home', 'home', '2016-08-27T17:48:32', true ], [ 2, 'About Us', 'about', '2016-08-28T08:42:09', true ], [ 4, 'Contact Us', 'contact', '2016-08-28T13:28:18', false ], ... ] ... }
dynamic.pipe.ts
import { Pipe, PipeTransform } from '@angular/core'; // Library used to humanize a date in this example import * as moment from 'moment'; @Pipe({name: 'dynamic'}) export class DynamicPipe implements PipeTransform { transform(value:string, modifier:string) { if (!modifier) return value; // Evaluate pipe string return eval('this.' + modifier + '(\'' + value + '\')') } // Returns 'enabled' or 'disabled' based on input value statusFromBoolean(value:string):string { switch (value) { case 'true': case '1': return 'enabled'; default: return 'disabled'; } } // Returns a human friendly time format e.g: '14 minutes ago', 'yesterday' humanizeDate(value:string):string { // Humanize if date difference is within a week from now else returns 'December 20, 2016' format if (moment().diff(moment(value), 'days') < 8) return moment(value).fromNow(); return moment(value).format('MMMM Do YYYY'); } } export const DYNAMIC_PIPES = [DynamicPipe];
table.component.html
<table> <thead> <td *ngFor="let head of data.header">{{ head }}</td> </thead> <tr *ngFor="let row of table.rows; let i = index"> <td *ngFor="let column of row">{{ column | dynamic:table.pipes[i] }}</td> </tr> </table>
Resultado
| ID | Page Title | Page URL | Created | Status | --------------------------------------------------------------------- | 1 | Home | home | 4 minutes ago | Enabled | | 2 | About Us | about | Yesterday | Enabled | | 4 | Contact Us | contact | Yesterday | Disabled | ---------------------------------------------------------------------
Probando un tubo
Dada una tubería que invierte una cuerda.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'reverse' })
export class ReversePipe implements PipeTransform {
transform(value: string): string {
return value.split('').reverse().join('');
}
}
Se puede probar configurando el archivo de especificaciones como este.
import { TestBed, inject } from '@angular/core/testing';
import { ReversePipe } from './reverse.pipe';
describe('ReversePipe', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ReversePipe],
});
});
it('should be created', inject([ReversePipe], (reversePipe: ReversePipe) => {
expect(reversePipe).toBeTruthy();
}));
it('should reverse a string', inject([ReversePipe], (reversePipe: ReversePipe) => {
expect(reversePipe.transform('abc')).toEqual('cba');
}));
});