Crear nuestros propios pipes

Vamos. No me digas que no lo has pensado. En los dos artículos anteriores hemos hemos comentado que podemos incluir, en nuestra aplicación Angular, nuestros propios pipes. Es cierto que el propio Angular incorpora bastantes, pero seguro que, antes o después, nos encontramos conque tenemos que cubrir una necesidad que no está prevista.

En este artículo vamos a aprender a crear un pipe «de nuestra propia cosecha», y a usarlo en nuestra aplicación. Verás que, aunque suene muy llamativo, es extremadamente simple, siempre y cuando, por supuesto, conozcas JavaScript (y si estás leyendo esto, está claro que lo conoces). Verás que es la tecnología del chupete.

Plantearemos una necesidad de modificar la presentación de un literal, y la programaremos como un pipe.

LA NECESIDAD

Vamos a empezar planteando la necesidad que queremos resolver. Se trata de hacer un recorte de cadenas literales demasiado largas. Pero queremos afinar un poco más de lo que hace el pipe slice que ya conocemos. Queremos establecer un máximo de caracteres, de modo que, si nuestro literal supera ese máximo sea recortado, pero no exactamente al máximo, si no en donde términa la última palabra que va a aparecer entera. Es decir, no queremos que nos corte una palabra, sino que el corte sea al final de la última palabra que puede aparecer completa.

Suponte que tienes el siguiente literal:

Esto es un literal demasiado largo, que queremos recortar a un máximo de 30 caracteres.

Y lo vamos a recortar, como se indica en la misma frase, a 30 carácteres como máximo. Si, a partir de ese literal, recortamos 30 caracteres, nos quedaremos con:

Esto es un literal demasiado l

Como ves, el corte se produce «dentro» de la palabra largo, con lo que esta aparece truncada, lo que queda tremendamete feo. Lo suyo es recortar justo cuando acaba la palabra anterior, de modo que el recorte nos quede así:

Esto es un literal demasiado

Y, además, queremos que se añadan al final, tres puntos suspensivos (...) para indicar que el literal continúa, y que está truncado, de modo que nos quede así:

Esto es un literal demasiado...

Además, queremos que si el literal no alcanza el máximo de longitud establecida nos lo devuelva íntegro, sin recortar.

Y todo eso lo queremos en un pipe, al que le pasemos como parámetro la longitud máxima deseada.

CREANDO EL PIPE

Lo primero que vamos a hacer, ahora que ya sabemos exactamente lo que queremos, es crear el pipe. Para alojar nuestros propios pipes (en una aplicación podemos crear todos los que deseemos), vamos a crear un directorio, en la estructura de la aplicación, dentro de src/app/, al que llamaremos pipes. Podríamos haberlo llamado como quisiéramos, pero lo suyo es darle al directorio un nombre descriptivo de lo que va a contener.

A continuación usaremos el comando ng generate. Ya lo hemos usado para crear módulos y componentes. Ahora vamos a usarlo para crear un pipe al que llamaremos, por ejemplo, SmartTruncate. Lo haremos así:

ng generate pipe pipes/SmartTruncate

O, abreviadamente, así:

ng g p pipes/SmartTruncate

Observa que le indicamos que lo cree en el directorio pipes. La consola nos responde con:

create src/app/pipes/smart-truncate.pipe.spec.ts (216 bytes)
create src/app/pipes/smart-truncate.pipe.ts (215 bytes)
update src/app/app.module.ts (891 bytes)

Observa la última línea. Vemos que se ha modificado el archivo app.module.ts. Esto es algo que Angular hace de forma automática, «asumiendo» que el nuevo pipe va a ser empleado en componentes que pertenezcan a AppModule. En concreto, las modicificaciones que hace las ves a continuación:

Como no es el caso (no vamos a usar el pipe en AppModule), debemos eliminar la primera línea resaltada y, en la segunda, eliminar la referencia al pipe. Si no, obtendremos erores de compilación, y no podremos ejecutar la aplicación.

Continuamos. El fichero con la terminación .spec.ts no nos importa por ahora. Al igual que con los componentes, es para test unitarios y de integración, que es un tema del que ya hablaremos. El que nos importa en este momento es smart-truncate.pipe.ts, cuyo listado original, recién creado, es el siguiente:

En la línea 1 se importa la clase Pipe, y la interface PipeTransform, ambas necesarias para que funcione el pipe.

Observa el decorador, que se inicia en la línea 3. En el contexto de los pipes, el decorador se llama, precisamente, así: @Pipe. contiene una propiedad básica que es el nombre con el que luego se invocará al pipe.

Por último, a partir de la línea 6, se declara y exporta la clase del pipe, con el nombre completo del mismo, implementando la interface PipeTransform. Dentro de esta clase se declara una función de TypeScript, que será la que reciba un valor, y los parámetros necesarios, ejecute toda la operativa, y devuelva el resultado.

El método transform procede de la interface. Aquí lo sobrescribimos y es el encargado de desplegar la «magia» del pipe. Recibe un parámetro obligatorio que, por defecto, se llama value, aunque tú puedes renombrarlo como desees. Este parámetro será el literal al que se aplique el pipe en su momento. El segundo parámetro que, por defecto aparece como args, con el comodín de opcional (esto es básico de TypeScript). representa al argumento que se le pasará al pipe para funcionar. Si queremos, podemos declarar más parámetros.

En el método transform programaremos el código JavaScript necesario para lo que deseemos que haga el pipe, y devolveremos el resultado adecuado. En el caso del ejemplo con el que hemos abierto este artículo, el código podría quedar así:

Recibimos una cadena en el parámetro originalString, y una longitud máxima en maxSize. El código JavaScript que hace el recorte según las especificaciones que pedimos al principio es un manejo de cadenas tan elemental que ni nos vamos a detener. Échale un vistazo rápido, y verás lo extremadamente simplón que es.

USANDO EL PIPE

Vale. Ya tenemos el pipe creado en la aplicación. Ahora hay que usarlo. Lo primero es saber en qué módulo está el componente donde lo queremos emplear. Como, en este caso, lo vamos a usar en PipesCheckingComponent, que es parte de PipesUsingModule, vamos a modificar el archivo pipes-using.module.ts para que importe el nuevo pipe, a fin de tenerlo disponible en el módulo, así:

Observa, en las líneas resaltadas, como lo importamos, para todo el módulo, y lo añadimos a la propiedad declarations del decorador.

Ahora vamos a definir, en la lógica del componente donde vamos a probar el pipe (pipes-checking.component.ts, en este ejemplo) un literal lo suficientemente largo como para que podamos experimentar con el pipe. Lo hacemos con la línea resaltada a continuación:

Y, por fin, llega la hora de la verdad. Vamos a implementar el pipe nuevo en pipes-checking.component.html:

Observa, en la línea resaltada, que lo llamamos con el nombre que tiene la propiedad name, en el decorador @Pipe, en smart-truncate.pipe.ts. Cuando es invocado, la cadena del literal (cadenaParaRecortar) entra en el parámetro originalString del método transform. El valor '30' entra en el parámetro maxSize del mismo método, y lo que el método retorna llega al viewport del navegador.

CONCLUYENDO

Y ya está. Ya sabemos crear pipes, y usarlos en nuestra aplicación. En este enlace tienes la aplicación, en su estado actual, para que experimentes con ella. Y seguimos adelante en el próximo artículo, aprendiendo sobre Angular.

   

Deja un comentario