Completando la lista de miembros

En el artículo anterior aprendimos a integrar DataTables en nuestro proyecto Angular 6. Sin embargo, lo que hicimos nos quedó imcompleto. En este artículo vamos a ampliarlo, añadiendo, para los administradores de nivel full, la posibilidad de crear los botones de edición y borrado de un socio. El botón de crear un nuevo miembro lo dejaremos para más adelante.

Con esto, nos quedará el CRUD de socios casi completo, tal como lo teníamos ya, pero usando DataTables, lo que siempre proporciona mejores resultados finales.

Aprenderemos a leer columnas que no se van a mostrar tal cual, sino adaptadas a nuestras necesidades. Ya hicimos un tosco acercamiento a esto cuando mostrábamos las fechas en formato español (sabemos que, en la base de datos están en formato ISO 8601 extendido). En este artículo vamos a dar un paso más creando elementos con los datos recibidos.

LO QUE TENEMOS QUE HACER

En este artículo vamos a hacer varias cosas interesantes:

  • En primer lugar, si el administrador logueado tiene el rol ROLE_FULL, le mostraremos los botones de edición y borrado. Esto es más sencillo de lo que parece.
  • Si se pulsa el botón de edición, se pasará al componente adecuado, para editar la ficha del socio. Esta parte no tiene nada nuevo respecto a como lo habíamos hecho anteriormente.
  • Si se pulsa el botón de borrado, se mostrará el modal para pedir confirmación. También funciona como ya conocemos.
  • Por último, si se borra un socio, se debe redibujar la tabla, para que el miembro borrado ya no aparezca. Esto, que en proyectos no Angular se resolvía con una simple instrucción, en un proyecto Angular es más complejo, y requiere varias novedades. Esta será, sin duda, la parte más ardua del artículo, pero es algo que debemos conocer para nuestros proyectos. Además, una vez aprendido el mecanismo, para otros proyectos es tan simple como copiar y pegar, cambiando, únicamente, los nombres de los elementos interesados.

LOS BOTONES DE EDICIÓN Y BORRADO

Lo primero que tenemos que hacer, en la lógica de MembersListComponent, es recuperar el id de cada miembro. Eso no es problema, porque la API ya nos proporciona todos los datos de cada registro leido, así que, en realidad, ya lo estábamos haciendo, aunque no mostrásemos ese campo en la lista de columnas.

En la vista, si tenemos el rol de admin de mayor rango, sí tenemos que mostrar dos columnas más en la tabla, para los botones. La cabecera de la tabla la recrearemos así:

Como ves, las dos últimas casillas están supeditadas a que el administrador logueado sea del rol ROLE_FULL. Además, si aparecen estas celdas en la cabecera, debemos crearlas, también, en las filas, así:

Observa las líneas resaltadas. Hemos construido, al igual que hacíamos antes, los botones con datos que obtenemos de la lógica del componente.

El funcionamiento de estos botones es el mismo que ya conocemos. Si se pulsa el botón de edición, el enrutador del módulo nos conduce al formulario que nos permite editar la ficha del miembro. Si se pulsa el botón de borrado, se activa un modal para pedir confirmación. No hay ninguna novedad en esto.

RECONSTRUIR LA TABLA TRAS UN BORRADO

Esta parte si es más peliaguda. Para recrear una tabla de DT hay que contar con un trigger, esto es, un disparador que lance la desctrucción de la tabla actual, y su recarga. Este tiene que estar bindeado a la propiedad dtTrigger de la tabla en la vista. Esta propiedad es la que permite que, cuando se dispara el trigger en la lógica, se actualice la vista. Lo vemos en la declaración de la tabla:

En la vista ya no tenemos más de que ocuparnos. Bueno, sí. Cuando descargues la aplicación, verás que están los avisos de «Operación correcta» o «Error en el proceso», como ya teníamos, pero estos funcionan como siempre, mediante variables lógicas, y no hay nada nuevo en ellos. Con el HTML ya hemos terminado.

En la lógica es donde la cosa es más engorrosa. En primer lugar, tenemos que empezar haciendo más importaciones. Desde el nucleo de Angular (@angular/core) nos hemos traido AfterViewInit, OnDestroy y ViewChild. Las dos primeras son interfaces que vamos a necesitar para el proceso. ViewChild define un tipo de decorador que usaremos para cargar la declaración de una de las clases propias de DataTables.

La clase que vamos a cargar mediante el decorador ViewChild es DataTableDirective que, internamente, maneja algunas operativas de DT. También tenemos que importarla en nuestro componente.

Además, debemos importar la clase Subject, de rxjs. Como sabemos, esta es una librería gratuíta, de uso libre, desarrollada por Microsoft. La clase Subject es una forma particular de observable, que nos permite encapsular el tipo DataTableDirective para gestionarlo.

Las importaciones, por lo tanto, nos quedan así:

En las líneas resaltadas ves las importaciones nuevas que hemos añadido.

Lo siguiente es implementar las interfaces AfterViewInit y OnDestroy en la declaración de la clase de nuestro componente, así:

export class MembersListComponent implements AfterViewInit, OnDestroy, OnInit {

Como ya sabes, eso significa que tendremos que sobrescribir los métodos ngAfterViewInit() y ngOnDestroy(), declarados en estas interfaces. Ya llegaremos a eso.

Ahora tenemos que usar el decorador de ViewChild para recibir la clase DataTableDirective. A partir de ahí crearemos un elemento (al que, en este ejemplo, vamos a llamar dtElement) para poder gestionar la tabla, y un trigger (al que vamos a llamar, en este ejemplo, dtTrigger), para poder disparar la reconstrucción de la tabla cuando lo necesitemos:

Ahora, al final del código (esto es por cuestiones organizativas, para que nos quede ordenado, no por causas operativas) redefinimos los métodos que hemos implementado a partir de las interfaces, y creamos un método, al que vamos a llamar reDraw(), que será, realmente, el encargado de redibujar la tabla cuando llegue el momento. Nos queda así:

El método reDraw() es invocado cuando el borrado de un elemento ha finalizado adecuadamente. Veamos que hace:

  • En primer lugar crea una instancia del elemento que representa a la tabla. La instancia la hemos llamado dtInstance y, como ves, la sintaxis es un poco arcana, ya que usa una promesa de JS para crearla, siendo del tipo DataTables.Api. Esto es parte del código del DataTables para Angular. No vamos a detenernos en como funciona «por dentro», porque excede de lo que pretendemos aquí.
  • Después, destruye esa instancia con el método destroy(). Como la instancia está apuntando a la tabla, realmente se está destruyendo la tabla. Es decir. La instancia no es una copia de la tabla. Es un puntero a la tabla.
  • Cuando se produce la destrucción, el método ngOnDestroy() se ocupa de «aislar» el trigger de la tabla que hemos destruido, mediante el uso del método unsubscribe().
  • Por último, el méto next() del trigger recrea la tabla, con lo que se vuelven a leer los datos que ahora quedan. Al recrearse la tabla, el trigger vuelve a quedar «suscrito» al observable de clase Subject, por lo que estará disponible para el próximo borrado.

El proceso no es fácil de entender, eso es cierto. Implica el uso de clases y elementos del DataTables de Angular, de la librería rxjs, que requeriría un libro entero sólo dedicado a ella, y muchos conceptos no habituales. Desde luego, como intentes entenderlo paso a paso, te aseguro que te vas a tirar muchas semanas buceando por foros y blogs. Sin embargo, seamos claros. No merece la pena ese esfuerzo y tiempo. Basta con tener el código a mano, y copiar y pegar cuando haga falta. Lo único que tienes que tener en cuenta es que los nombres del elemento DataTables, del trigger, de la instancia, etc coincidan en donde hagan falta, para evitar errores.

CONCLUYENDO

Este artículo termina aquí. Como siempre, la aplicación, en su estado actual, puedes descargarla en este enlace. En el próximo artículo añadiremos el botón de crear nuevo usuario, y alguna cosa más, para mejorar nuesta lista de miembros.

   

Deja un comentario