Mejorando la lista de socios

Ya tenemos nuestro CRUD de socios operativo con DT. Sin embargo, como apuntábamos en el artículo anterior, ya que estamos empleando una librería externa tan potente y flexible como DataTables, y ya llegados a este punto, sería absurdo no aprender más sobre el particular. Es evidente que no podemos detallar todas las prestaciones de DT, ya que son muchas, y el fabricante, así como terceros, añaden muchas más con frecuencia. Sin embargo, si vamos a «pulir» nuestra técnica de trabajo, de modo que, si en un momento dado, necesitamos más extensiones, sepamos como añadirlas y emplearlas.

Algo que debo comentarte es que, si añades extensiones a tu DT, tanto en un proyecto Angular como no Angular, procures contar, de manera preferente, con extensiones y complementos desarrollados por el fabricante y publicados en su página oficial. Si bien hay terceros que desarrollan plugins para DT, estos no siempre tienen la credibilidad, fiabilidad, seguridad y mantenimiento que sería de esperar. Si instalas un complemento de terceros, asegúrate del origen del mismo. Si tienes dudas al respecto, o las opiniones o comentarios en Internet son escasos o contradictorios, mejor renuncia.

EL PRIMER PASO

El primer paso para poder manipular los datos que se muestran en la tabla con mayor flexibilidad es cambiar el punto donde se muestran. Hasta ahora, una vez obtenidos los datos, los almacenábamos en una matriz, y la mostrábamos desde la vista con la directiva estructural *ngFor. Eso ahora ya no es así. En la vista sólo se define la tabla, pero no se renderiza la cabecera de la misma, ni las filas de datos. Nos queda así:

Como ves, hemos suprimido todos los datos en la vista. Por lo tanto, en la lógica, ya no necesitamos los datos que antes se preparaban para mostrar en la tabla. Suprimimos las variables Members y NumberOfMembers. Además, y esto es de vital importancia, sustituimos la línea:

data: []

por:

data: resp.data

Al introducir los datos de la tabla en la propiedad data que, hasta ahora, estaba vacía, es el controlador el que renderiza estos datos, de forma automática y transparente, en la vista. Después de todo, la declaración de la tabla en HTML está enlazada con la tabla en el controlador a través del bindeado de dtOptions y dtTrigger que juegan, cada vez, un papel más relevante.

HUY, SI FALTAN COSAS

Sí. Así es. Si has entrado con el administrador de ROLE_FULL, ya te habrás dado cuenta de que nos faltan los botones de edición y borrado de cada miembro. Está claro. Antes los renderizábamos en la tabla, y ahora ya no. A ver como lo resolvemos.

Tenemos que crear dos nuevas columnas. Cada una de ellas tendrá un botón por fila (el de edición y el de borrado). La forma de crearlas es la siguiente:

Veamos que contienen, porque esta parte es muy interesante. Estamos aprendiendo a crear columnas personalizadas en DT desde el controlador.

  • El atributo title contiene el encabezado de la columna. Sustituye al contenido de las celdas de cabecera (<th>) cuando renderizábamos la tabla en la vista.
  • El atributo width establece el ancho de la columna, aunque ya te aviso que no todos los navegadores muestran correctamente este atributo cuando aparece en la definición de una columna.
  • El atributo render es el más relevante. Es el que crea físicamente el botón (aunque no su operativa; de eso hablaremos un poco más adelante en este mismo artículo). Este atributo incluye una función anónima que recibe tres argumentos, llamados, por defecto, data, type y full. De estos tres sólo emplearemos el que llamamos full, pero hhay que definirlos todos, para declarar correctamente la firma de la función. El atributo full es una matriz JSON que contiene todos los datos recuperados de cada miembro. Dentro de la función declaramos el HTML necesario para definir el botón. Como ves, es un HTML muy simple. Lo más llamativo es que establecemos el atributo id, haciéndolo coincidir con el id del registro (miembro, o socio) al que se refiere cada fila. También nos interesa el atributo name, al que le damos un identificativo del botón (editButton o deleteButton, en este ejemplo), para luego poder crearle a cada uno su operativa. Además, como en el botón de borrado necesitamos el nombre del socio que vamos a borrar, se lo asignamos al atributo value, para poder recuperarlo en la operativa.
  • Los atributos searchable y orderable, con el valor false, determinan que estas columnas no serán criterio de ordenación de la tabla, ni se podrá buscar nada en ellas.
  • Por último, fíjate en el valor visible. Este será true, si el administrador logueado tiene el rol ROLE_FULL, o false, en caso contrario (ROLE_ADMIN). De eso nos ocupamos más arriba, aunque lo comentaremos un poco más adelante en este mismo artículo.

La operativa de estos dos botones debemos «sujetarla» a uno de los lifecycle hooks que empleamos. En concreto, al método ngAfterViewInit(), que ya empleamos en el borrado de elementos en el artículo anterior. Previamente, debemos importar otra clase de Angular, llamada Renderer. Pertenece al núcleo de Angular, y la importamos en la primera línea del código, como verás cuando te lo bajes. Además, creamos un objeto de esta clase, al que podemos llamar renderer (por ejemplo), en la firma del constructor. Con este ojeto ya podemos crear la operativa. El método ngAfterViewInit() nos queda así:

Observa que usamos el objeto de la clase Renderer para crear un escuchador de eventos, con el método listenGlobal(). Lo que hacemos es detectar cualquier pulsación ('click') en el documento ('document'). Esto genera un evento ('event') con el que detectaremos la pulsación de los botones de edición o borrado. El evento tiene un atributo llamado target. A través de este, nos llegan los atributos del botón pulsado. La acción a realizar la determina el name. El elemento (socio) al que corresponde lo determina el id. Por último, en el caso del botón de borrado, el nombre del socio nos llega por value. A partir de estos datos, en el caso de edición saltamos al correspondiente componente, y en el caso del borrado lanzamos el método preavisoDeBorrado(). Observa que a este método le hemos retocado la firma, porque ahora ya no recibe un objeto Member completo como antes, sino el id y el nombre.

Como ves, al principio impresiona un poco pero, a nada que te detienes a analizarlo, más simple no puede ser.

LOS BOTONES DE LA PARTE SUPERIOR

Como ya apuntábamos en el artículo anterior, ya que usamos la esxtensión de botones de DT, vamos a sacarle un poco más de partido. En concreto, vamos a añadir dos botones, para volvar los resultados a una tabla de excel, o imprimirlos en papel. Para ello, existen dos clases que declaran los correspondientes botones. A partir de estas, crearemos nuestros propios botones. En este ejemplo lo hemos hecho así:

Observa que cada botón tiene los siguientes atributos:

  • El atributo extend determina la clase a partir de la que deriva el botón. Estas clases son propias de la extensión de botones de DT, por lo que no necesitamos declararlas en ninguna parte. Ya nos vienen dadas.
  • El atributo text determina la etiqueta que se mostrará en el boton.
  • El atributo exportOptions determina las columnas que van a ser afectadas por cada operación. En el caso de la impresión, o la exportación a excel, no tiene ningún sentido que exportemos las columnas con los botones de edición o borrado, por lo que sólo incluiremos las tres primeras. Como se empiezan a numerar desde 0, incluiremos, como ves, la 0, la 1 y la 2.
  • En el botón destinado a imprimir, además, tenemos el atributo autoPrint, con el valor true. Esto hace que, además de mostrar la vista de impresión, se muestre el cuadro de dialógo de la impresora que vayamos a usar.

COLOCANDO LOS BOTONES

Ahora tenemos que determinar si el usuario es ROLE_ADMIN o ROLE_FULL. En este último caso, a la lista de botones añadiremos el de crear un nuevo socio, que ya conocemos, y pondremos visibles las dos últimas columnas que hemso creado:

CONCLUYENDO

Cómo has podido ver en este artículo, generar la tabla con los datos a partír del controlador, en lugar de hacerlo desde la vista, nos da más posibilidades que, de otro modo, no podríamos obtener adecuadamente. Por lo tanto, en lo sucesivo, lo haremos así casi siempre. Sólo en el caso de tablas muy simples, que no requieran ninguna operativa especial, mostraremos los datos desde la vista.

Como siempre, en este enlace tienes la aplicación en su estado actual. Con este artículo damos por terminada la integración de DataTables en proyectos Angular. Aunque DT tiene otras extensiones interesantes, hemos visto las más habituales. En el caso de querer usar otras, nos documentaremos en el sitio oficial del fabricante.

Lo que sí añadiremos aquí es la forma de cargar las extensiones DT más usadas en un proyecto Angular, de modo que, cuando consultes la documentación oficial, no tengas más que seguir sus instrucciones para que todo te funcione correctamente. En el proyecto Angular haz las siguientes instalaciones:

Las líneas resaltadas corresponden a las extensiones DT que no hemos usado en este curso, pero que dejaremos instaladas por si las necesitàramos más adelante.

Las secciones styles y scripts del archivo angular.json nos quedarán así:

Una vez más, las líneas resaltadas corresponden a extensiones que no hemos empleado en este curso. No obstante, en la aplicación que te descargas correspondiente a este artículo las tienes ya instaladas, por si deseas experimentar con ellas por tu cuenta.

   

Deja un comentario