1. Introducción y Objetivos de Aprendizaje:
- ¡Hola, desarrolladores! 👋 Hoy nos sumergiremos en una de las características más elegantes de Angular: los Pipes 💧. Imaginen que tienen datos crudos en su componente (una fecha 📅, un número #️⃣, un texto largo 📜), pero necesitan mostrarlos en la plantilla HTML con un formato específico (fecha corta, moneda 💰, texto abreviado). Los Pipes son los "transformadores" 🪄 que nos permiten hacer esto directamente en el HTML, de forma limpia y reutilizable.
- Desde una perspectiva de arquitectura de software 🏗️, los Pipes son cruciales para adherirse al principio de Separación de Responsabilidades. La lógica de cómo mostrar los datos (formateo) pertenece a la capa de presentación (la plantilla), no necesariamente a la lógica de negocio del componente. Los Pipes encapsulan esta lógica de transformación ⚙️, haciéndola testeable ✅, reutilizable 🔄 y manteniendo los componentes más ligeros y enfocados en gestionar el estado y la interacción. Además, Angular optimiza el uso de Pipes (especialmente los "puros") para un rendimiento eficiente 🚀.
- (Nota de Repaso): Al finalizar esta nota, usted podrá:
- ✅ Definir qué es un Pipe en Angular y cuál es su propósito principal.
- ✅ Identificar y utilizar los Pipes incorporados (built-in) más comunes de Angular.
- ✅ Comprender cómo pasar argumentos a los Pipes para personalizar la transformación.
- ✅ Encadenar múltiples Pipes para aplicar varias transformaciones secuencialmente.
- ✅ Crear y utilizar sus propios Pipes personalizados (Custom Pipes).
- ✅ Distinguir entre Pipes Puros e Impuros y entender sus implicaciones de rendimiento.
- ✅ Aplicar Pipes correctamente en las plantillas HTML de Angular usando la sintaxis
|
.
2. Conceptos Fundamentales (Definiciones Clave):
- Pipe 🔧: Una clase decorada con
@Pipe
que implementa la interfazPipeTransform
. Su función principal es transformar un valor de entrada en un valor de salida formateado para ser mostrado en una plantilla HTML. - Transformación 🔄: El proceso de convertir datos de un formato a otro (ej: objeto
Date
a stringdd/MM/yyyy
, número1234.56
a string$1,234.56
). -
PipeTransform
(Interfaz) 📝: Interfaz que debe implementar toda clase Pipe. Define un único método obligatorio:transform
. -
transform(value: any, ...args: any[]): any
(Método) ✨: El corazón del Pipe. Recibe el valor original (value
) que fluye desde la izquierda del operador|
en la plantilla, y opcionalmente, argumentos adicionales (args
) pasados después de dos puntos (:
). Debe devolver el valor transformado. - Sintaxis en Plantilla (
➡️ |
): El operador "pipe" se usa en las expresiones de interpolación ({{ }}
) o en los data bindings ([property]="expression | pipe"
) para aplicar un Pipe.{{ valor | nombreDelPipe }}
. - Argumentos de Pipe (
➡️ :
): Se pasan argumentos adicionales al métodotransform
usando dos puntos después del nombre del Pipe.{{ valor | nombreDelPipe:arg1:arg2 }}
. - Encadenamiento de Pipes ⛓️: Aplicar múltiples Pipes secuencialmente. La salida de un Pipe se convierte en la entrada del siguiente.
{{ valor | pipe1 | pipe2:arg1 }}
.
3. Desarrollo del Tema: El Poder de los Pipes en Acción 🛠️
Piensen en los datos fluyendo a través de "tuberías" (pipes) en su plantilla 💧➡️💧➡️🖥️. Cada tubería toma el dato, le hace algo (lo formatea, lo filtra, lo modifica) y lo pasa al siguiente, o finalmente lo muestra en la pantalla.
-
Profundicemos en los detalles técnicos y casos de uso:
A. ¿Por qué usar Pipes?
- ✅ Legibilidad del Template: Mantiene las expresiones en HTML limpias.
{{ fechaCumpleanos | date:'shortDate' }}
vs{{ formatearFechaCorta(fechaCumpleanos) }}
. - ✅ Reutilización: La lógica de formato es reutilizable en toda la app.
- ✅ Separación de Responsabilidades: Componente (qué datos) vs Pipe (cómo mostrarlos).
- ✅ Performance (Pipes Puros): Angular optimiza su ejecución 🚀.
- ✅ Testabilidad: Fáciles de probar unitariamente 🧪.
B. Cómo Llamar Pipes desde HTML 💻:
-
Sintaxis Básica:
{{ expresionAngular | nombrePipe }}
{{ titulo | uppercase }}
-
Con Argumentos ⚙️:
{{ expresionAngular | nombrePipe:argumento1:argumento2:... }}
Fecha: {{ fechaActual | date:'dd/MM/yyyy' }} Número: {{ numeroGrande | number:'1.2-2' }}
-
Encadenamiento ⛓️:
{{ expresionAngular | pipe1 | pipe2:argPipe2 | pipe3 }}
{{ descripcionLarga | slice:0:15 | uppercase }}...
C. Pipes Incorporados (Built-in) Más Comunes:
- 📅
DatePipe
: Formatea fechas.{{ miFecha | date:'medium' }}
. - 🅰️
UpperCasePipe
: Convierte texto a MAYÚSCULAS.{{ texto | uppercase }}
. - 🔡
LowerCasePipe
: Convierte texto a minúsculas.{{ texto | lowercase }}
. - 📖
TitleCasePipe
: Convierte texto a Formato Título.{{ texto | titlecase }}
. - #️⃣
DecimalPipe
(number
): Formatea números.{{ numero | number:'1.0-2' }}
. - %
PercentPipe
: Formatea números como porcentajes.{{ 0.25 | percent }}
(25%). - 💰
CurrencyPipe
: Formatea números como moneda.{{ precio | currency:'USD':'symbol' }}
($1,234.56). - {}
JsonPipe
: Convierte objeto/array a JSON string (ideal para debug).{{ miObjeto | json }}
. - ✂️
SlicePipe
: Extrae sub-sección de array/string.{{ miArray | slice:1:3 }}
. - 🔑
KeyValuePipe
: Itera sobre objetos/Maps en*ngFor
.*ngFor="let item of miObjeto | keyvalue"
. - ⏳/⚡️
AsyncPipe
: Se suscribe/desuscribe a Observables/Promises.{{ miObservable$ | async }}
.
D. Creando Pipes Personalizados (Custom Pipes) 🔧:
- Generación (CLI) ⌨️:
ng generate pipe nombre-del-pipe
(ej:ng g p truncate
). -
Implementación ✍️: Edita
nombre-del-pipe.pipe.ts
, implementatransform()
.
// Ejemplo: truncate.pipe.ts import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'truncate', standalone: true }) export class TruncatePipe implements PipeTransform { transform(value: string, limit: number = 20, trail: string = '...'): string { // ... (lógica de truncar) ... return value.length > limit ? value.substring(0, limit) + trail : value; } }
- ✅ Legibilidad del Template: Mantiene las expresiones en HTML limpias.
3. Registro ✅:
* Standalone Components: Importa en `imports: [..., TruncatePipe]`.
* NgModules: Declara en `declarations: [...]`.
4. Uso en Plantilla 💻: `{{ miTexto | truncate:100:' ->' }}`.
Pipes Puros vs. Impuros:**
* Pipes Puros 💧 (`pure: true` - por defecto):
* Se ejecutan solo con cambios *puros* (primitivos o referencia de objeto).
* Ventaja: Muy eficientes 🚀.
* Pipes Impuros 🔥 (`pure: false`):
* Se ejecutan en *cada* ciclo de detección de cambios.
* Uso: Necesarios para cambios internos de objetos/arrays (sin cambio de referencia) o estado interno (ej: `AsyncPipe`, `JsonPipe`).
Precaución: ⚠️ ¡Pueden impactar el rendimiento! Usar con moderación.
4. Ejemplo Completo 🧪:
// en tu componente.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common'; // Para pipes built-in
import { TruncatePipe } from './truncate.pipe'; // Custom pipe
import { Observable, interval } from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-pipe-demo',
standalone: true,
imports: [CommonModule, TruncatePipe], // <-- Importados aquí
template: `
Demostración de Pipes 🧪
📅 Fecha actual (completa): {{ ahora | date:'fullDate' }}
📅 Fecha actual (corta): {{ ahora | date:'short' }}
📖 Título Original: {{ libro.titulo }}
🅰️ Título en Mayúsculas: {{ libro.titulo | uppercase }}
✂️ Título Truncado: {{ libro.titulo | truncate:15:'...' }}
💰 Precio: {{ libro.precio | currency:'EUR':'symbol':'1.2-2' }}
% Descuento: {{ libro.descuento | percent:'1.0-0' }}
{} Descripción (JSON Debug):
{{ libro | json }}
✂️ Tags (Primeros 2):
{{ tag | titlecase }}
⏳ Contador (Async Pipe): {{ contador$ | async }}
`
})
export class PipeDemoComponent {
ahora: Date = new Date();
libro = { /* ... datos del libro ... */ };
contador$: Observable<number> = interval(1000).pipe(map(i => i * 2));
}
5. Buenas Prácticas y Consideraciones Adicionales 👍:
*
* ✨ Prioriza Pipes Puros: Mejor rendimiento.
* ✨ Evita Lógica Compleja en Pipes: Mantenlos simples y enfocados.
* ✨ Reutilización: Crea Custom Pipes para lógica repetida.
* ✨ No Abuses del Encadenamiento: Puede reducir legibilidad.
* ✨ Cuidado con Pipes Impuros y *ngFor
: Considera trackBy
.
* 🌐 Internacionalización (i18n): Configura LOCALE_ID
para DatePipe
, CurrencyPipe
, etc.
- 👨🏫 ¡Revisa los Pipes built-in antes de crear uno! ¡Y prueba tus creaciones! 🧪
6. Resumen / Puntos Clave para el Repaso 📌:
- ✅ Pipes: Transforman datos en plantillas (
@Pipe
,PipeTransform
). - ✅ Propósito: Formateo, legibilidad, reutilización, separación.
- ✅ Sintaxis:
{{ valor | nombrePipe:arg1 }}
. Encadenables (| pipe1 | pipe2
). - ✅ Built-in: Date, Upper/Lower/TitleCase, number, Currency, Percent, Json, Slice, KeyValue, Async.
- ✅ Custom Pipes:
ng g p nombre
, implementatransform()
, importa/declara. - ✅ Puros (💧) vs. Impuros (🔥): Puros más eficientes, Impuros para casos específicos (¡cuidado!).
7. Preguntas de Autoevaluación 🤔:
- ❓ ¿Cuál es el beneficio principal de usar Pipes sobre métodos de componente para formato?
- ❓ Sintaxis para
DatePipe
con formato 'dd-MMM-yyyy'. - ❓ ¿Qué significa "Pipe puro" y por qué importa?
- ❓ ¿Cuándo usarías
AsyncPipe
? - ❓ Pasos para crear un Pipe
addPrefix
que añada "PRE:" a un string.