Pipes
Los Pipes sirven para transformar los datos que se muestran en el html sin alterarlos
Los Pipes se aplican usando "|". Apliquemos el Pipe "uppercase"
<!-- app.component.ts -->
...
export class AppComponent {
nombre: string = "nombre de Usuario"
...
}<!-- app.component.html -->
<p>
{{ nombre | uppercase }}
</p>NOMBRE DE USUARIO
En el navegador se mostrará así:
Apliquemos el Pipe "date"
<!-- app.component.ts -->
...
export class AppComponent {
fecha: string = new Date(2018, 6, 17)
...
}<!-- app.component.html -->
<p>
{{ fecha | date }}
</p>Jul 17, 2018
En el navegador se mostrará así:
Parametrizando
Supongamos que el formato de fecha no es el que queremos.
Supongamos que queremos mostrar la fecha completa (día de la semana, mes, día y año).
Para ello hay que usar los parámetros del Pipe "date".
Los Pipes, finalmente, son también clases que reciben un dato y opcionalmente parámetros para cambiar la forma cómo se muestra en el HTML.
Los parámetros de un Pipe se separan con ":" y con ", " como se suele hacer en un método o función.
El Pipe "date" está incluido en Angular y tiene ya definidos sus opciones de parámetros. Uno de ellos es "fullDate"
<!-- app.component.html -->
<p>
{{ fecha | date: "fullDate" }}
</p>Tuesday, July 17, 2018
En el navegador se mostrará así:
Encadenando Pipes
Los Pipes se pueden encadenar. Encadenar significa que se pueden aplicar un Pipe después de otro.
Por ejemplo quiero mostrar la fecha en formato completo y en mayúsculas.
<!-- app.component.html -->
<p>
{{ fecha | date: "fullDate" | uppercase }}
</p>TUESDAY, JULY 17, 2018
En el navegador se mostrará así:
El orden aplicación de Pipes es importante.
<!-- app.component.html -->
<p>
{{ fecha | date: "fullDate" | uppercase }}
</p>Lo siguiente es correcto.
<!-- app.component.html -->
<p>
{{ fecha | uppercase | date: "fullDate" }}
</p>Pero esto no lo es.
Crear un Pipe
Para crear un Pipe se necesita importar el decorador "@Pipe" y la interface "PipeTransform" desde "@angular/core"
import { Pipe, PipeTransform } from "@angular/core"Un Pipe tiene la siguiente sintaxis suponiendo que creamos un Pipe llamado "reducidor":
<!-- reducidor.pipe.ts -->
import { Pipe, PipeTransform } from "@angular/core";
@Pipe({
name: "reducidor"
})
export class ReducidorPipe implements PipeTransform {
transform() {}
}Para que el Pipe "reducidor" exista, debe declararse en un módulo.
<!-- app.module.ts -->
...
import { ReducidorPipe } from "./reducidor.pipe"
...
@NgModule({
...
declarations: [
ReducidorPipe
],
...
})Supongamos que tenemos la siguiente data:
<!-- app.component.ts -->
...
interface novela {
titulo: string;
autor: string;
descripcion: string;
}
...
export class AppComponent {
novelas: novela[] = [
{
titulo: "La ciudad y los perros",
autor: "Mario Vargas Llosa",
descripcion:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed interdum urna ac rhoncus semper. Nam mauris tellus, euismod nec suscipit nec, ullamcorper quis urna. Sed libero est, elementum ut magna vel, ultricies aliquet lorem. Proin vitae tellus et lectus rutrum suscipit. Vivamus et volutpat neque, eget porttitor nibh. Interdum et malesuada"
},
{
titulo: "El Sexto",
autor: "José María Arguedas",
descripcion:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed interdum urna ac rhoncus semper. Nam mauris tellus, euismod nec suscipit nec, ullamcorper quis urna. Sed libero est, elementum ut magna vel, ultricies aliquet lorem. Proin vitae tellus et lectus rutrum suscipit. Vivamus et volutpat neque, eget porttitor nibh. Interdum et malesuada"
},
{
titulo: "El Perfume",
autor: "Patrick Suskind",
descripcion:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed interdum urna ac rhoncus semper. Nam mauris tellus, euismod nec suscipit nec, ullamcorper quis urna. Sed libero est, elementum ut magna vel, ultricies aliquet lorem. Proin vitae tellus et lectus rutrum suscipit. Vivamus et volutpat neque, eget porttitor nibh. Interdum et malesuada"
},
{
titulo: "La tía Julia y el escribidor",
autor: "Mario Vargas Llosa",
descripcion:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed interdum urna ac rhoncus semper. Nam mauris tellus, euismod nec suscipit nec, ullamcorper quis urna. Sed libero est, elementum ut magna vel, ultricies aliquet lorem. Proin vitae tellus et lectus rutrum suscipit. Vivamus et volutpat neque, eget porttitor nibh. Interdum et malesuada"
}
}Supongamos que la mostramos en el HTML.
<!-- app.component.html -->
<div *ngFor="let novela of novelas">
<p>{{novela.titulo}}</p>
<p>{{novela.autor}}</p>
<p>{{novela.descripcion}}</p>
</div>Modifiquemos el Pipe "reducidor" para reducir la descripción a 30 caracteres.
El método "transform" puede tener varios parámetros. El primero siempre es el elemento sobre el cual se aplica.
<!-- reducidor.pipe.ts -->
...
export class ReducidorPipe implements PipeTransform {
transform(valor: any) {
if (valor.length < 30) return valor;
return valor.substr(0, 30);
}
}En el HTML.
<!-- app.component.html -->
<div *ngFor="let novela of novelas">
<p>{{novela.titulo}}</p>
<p>{{novela.autor}}</p>
<p>{{novela.descripcion | reducidor}}</p>
</div>Modifiquemos el Pipe "reducidor" para que la restricción de caracteres llegue como parámetro.
Nuestros parámetros en un Pipe se indican luego del primer parámetro.
<!-- reducidor.pipe.ts -->
...
export class ReducidorPipe implements PipeTransform {
transform(valor: any, limite: number) {
if (valor.length < limite) return valor;
return valor.substr(0, limite);
}
}En el HTML.
<!-- app.component.html -->
<div *ngFor="let novela of novelas">
<p>{{novela.titulo}}</p>
<p>{{novela.autor}}</p>
<p>{{novela.descripcion | reducidor: 30}}</p>
</div>Supongamos que queremos filtrar las novelas por el autor.
<!-- app.component.html -->
<input type="text" [(ngModel)]="filtro" placeholder="Búsqueda">
<div *ngFor="let novela of novelas | filtroNovela: filtro">
<p>{{novela.titulo}}</p>
<p>{{novela.autor}}</p>
<p>{{novela.descripcion | reducidor: 30}}</p>
</div>Creemos el Pipe "filtroNovela"
<!-- filtro-novela.pipe.ts -->
@Pipe({
name: "filtroNovela"
})
export class FiltroNovelaPipe implements PipeTransform {
transform(novelas: novela[], filtro: string): any {
if (!filtro) return novelas;
return novelas.filter((novela: novela) => {
return novela.autor.toLowerCase().indexOf(filtro.toLowerCase()) > -1
? true
: false;
});
}
}Supongamos que queremos filtrar por el autor o por el título.
<!-- app.component.html -->
<input type="text" [(ngModel)]="filtro" placeholder="Búsqueda">
<select name="campo" [(ngModel)]="campo">
<option value="autor">Autor</option>
<option value="titulo">Título</option>
</select>
<div *ngFor="let novela of novelas | filtroNovela: filtro: campo">
<p>{{novela.titulo}}</p>
<p>{{novela.autor}}</p>
<p>{{novela.descripcion | reducidor: 30}}</p>
</div>Modifiquemos el Pipe "filtroNovela" para que acepte un parámetro más.
<!-- filtro-novela.pipe.ts -->
@Pipe({
name: "filtroNovela"
})
export class FiltroNovelaPipe implements PipeTransform {
transform(novelas: novela[], filtro: string, campo: string): any {
if (!filtro) return novelas;
return novelas.filter((novela: novela) => {
return novela[campo].toLowerCase().indexOf(filtro.toLowerCase()) > -1
? true
: false;
});
}
}El Pipe "async"
Supongamos que creamos una promesa que nos devuelve una lista de autores.
<!-- app.component.ts -->
...
export class AppComponent {
autores: Promise<string[]>
ngOnInit(){
this.autores = new Promise<string[]>((resolve, reject) => {
setTimeout(()=>{
resolve([
"Mario Vargas Llosa",
"César Vallejo",
"Abraham Valdelomar"
])
},3000)
})
}
}En el html debemos aplicar el Pipe "async"
<!-- app.component.html -->
<div *ngFor="let autor of autores | async">
{{autor}}
</div>Tarea 1
- Modificar el Pipe "reducidor" para que la restricción no sea sobre la cantidad de caracteres sino sobre la cantidad de palabras.
- Tip: usar el método "split".