ng-content

ng-content

Usando Pipes para transformar datos

Usando Pipes para transformar datos

Dany Paredes's photo
Dany Paredes
·Apr 9, 2022·

4 min read

Subscribe to our newsletter and never miss any upcoming articles

Play this article

Table of contents

  • Usando el pipe currency
  • Creando el custom pipe.
  • Un poco más interactivo.
  • Final

Cuando necesitamos que nuestras aplicaciones muestren una información de una forma solamente para la visualización, en Angular podemos hacerlo gracias a los Pipes.

Angular nos permite convertir valores para ser visualizados de una manera específica sin alterarlos, en pocas palabras los Pipes nos permite tomar un dato y retornarlo transformado de la manera que queremos.

Una mala práctica comúnmente usada es utilizar un método en el template para convertirlo, para esos escenarios siempre utiliza un Pipe.

Los Pipes trabajan en conjunto con nuestros templates en los componentes utilizando el operando | obteniendo la data de izquierda a la función pipe en la derecha y esta retorna el dato transformado.

Angular viene con una lista de pipes además nos permite crear nuestras propias pipes para que retorne lo que nos interesa.

Puedes ver la lista de pipes https://angular.io/api/common#pipes

La idea en este post es usar un pipe de angular y crear uno a nuestras necesidades.

Usando el pipe currency

Suponemos que nos piden crear una interfaz en la cual muestre un listado de salarios, pero queremos ver los decimales y un formato de moneda.

salaryRanges = [
    {
      title: 'developer',
      salary: 90000,
    },
    {
      title: 'nbaPlayer',
      salary: 139883,
    },
    {
      title: 'doctor',
      salary: 72000,
    },
  ];

Para visualizarlos en el html usamos la directiva ngFor, algo como esto.

<ul>
  <li *ngFor="let profesional of salaryRanges">
    {{ profesional.title }}
    {{ profesional.salary }}
  </li>
</ul>

Inicialmente se visualizan de esta forma

developer 90000
nbaPlayer 139883
doctor 72000

Para cambiar la salida utilizando el pipe currency este por defecto utiliza USD como formato, este le agregara el símbolo de $ además de los decimales.

<ul>
  <li *ngFor="let profesional of salaryRanges">
    {{ profesional.title }}
    {{ profesional.salary | currency }}
  </li>
</ul>

Ahora el formato de salida sera de esta manera.

developer $90,000.00
nbaPlayer $139,883.00
doctor $72,000.00

Perfecto, nuestros salarios se visualizan con un formato, pero que pasaria si quisiera poder convertir esos salarios a dolares o euros ? angular no tiene algo para esto... entonces creamos un Pipe custom!

Nota una solucion no optima seria llamar un metodo, en el ngFor pasandole valor y haciendo el calculo pero esto no seria optimo.

Creando el custom pipe.

Un pipe no es más que una clase de typescript que implementa la interfaz PipeTransform, vamos a crear nuestro pipe convertExchange este tomara el valor y lo divide por 55 para así hacer la conversión.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'convertExchange'
})
export class ConvertToExchange implements PipeTransform {
  transform(value: any, args?: any): any {
    return value / 55
  }
}

Recuerda que al crear el pipe debes registrarlo en tu AppModule.

Nosotros podemos utilizar pipes anidados, por ejemplo convertExchange para generar el cálculo y currency para darle el formato.

Actualizamos nuestro html y usamos ambas pipes

{{ profesional.salary | convertToExchange | currency }}

Y el resultado final es

developer $1,636.36
nbaPlayer $2,543.33
doctor $1,309.09

Perfecto, nuestro pipe es capaz de convertir y darles formato, pero que pasaría si quisiéramos que el monto de cálculo sea dinámico, por ejemplo conversión de EUROS a USD.

¡Vamos a hacer ajustes!

Primero vamos a crear un objecto con el listado de monedas

const currencyValues = {
  USD: 55,
  EURO: 75,
};

En el método transform agregamos un nuevo parámetro currency, este se utilizará para obtener el valor relacionado con la moneda y luego hacer el cálculo en el transform, en caso de que no exista lo divide entre 1.

El código final será algo como esto:

import { Pipe, PipeTransform } from '@angular/core';
const currencyValues = {
  USD: 55,
  EURO: 75,
};

@Pipe({
  name: 'convertToExchange'
})
export class ConvertToExchange implements PipeTransform {
  transform(value: any, currency: string): any {
    return value / this.getCurrencyValue(currency);
  }

  getCurrencyValue(currency) {
    return currencyValues[currency] | 1;
  }
}

Perfecto, nuestro pipe recibirá el tipo de moneda y hará el cálculo para la conversión.

Para enviar el valor solo tenemos que usar : después del pipe.

{{ profesional.salary | convertToExchange: 'USD' | currency }}

La salida final seria:

developer $1,636.36
nbaPlayer $2,543.33
doctor $1,309.09

Perfect! Nuestro pipe permite recibir parámetros, pero ahora tenemos que cambiar de manera manual y si quisiéramos que el usuario elija el formato de moneda desde un select. ¡Vamos a eso!!

Un poco más interactivo.

Creamos un select con el listado de monedas para el usuario pueda seleccionar, en el evento change actualizaremos una propiedad nueva llamada currentCurrency utilizando un nuevo método llamado changeTo que por defecto será DOP que no existe, por tanto, retornara 1.

<select (change)="changeTo($any($event.target).value)">
  <option value="USD">USD</option>
  <option value="EURO">EURO</option>
  <option selected>DOP</option>
</select>

En el componente creamos la propiedad y el método.

currentCurrency = 'DOP';
changeTo(currency) {
    this.currentCurrency = currency;
  }

Ya lo siguiente será usar la nueva propiedad currentCurrency en el template como parámetro para nuestro pipe.

<li *ngFor="let profesional of salaryRanges">
    {{ profesional.title }}
    {{ profesional.salary | convertToExchange: currentCurrency | currency }}
  </li>

Final

En resumen, los pipes son muy poderosos, pero te recomiendo que mires la documentación oficial de angular, donde verás muchos más ejemplos.

https://angular.io/guide/pipes

Puedes jugar con el demo del proyecto en stackbliz.

Photo by T K on Unsplash

 
Share this