Angular Search & Pagination

Componente de paginación

Para nuestro componente de paginación, lo que tenemos que hacer son dos cosas principales: renderizar todos los números de página posibles para que el usuario elija y detectar cuando la página ha cambiado para recuperar los datos de la página elegida.

En primer lugar, vamos a añadir a nuestro componente una propiedad Input para recibir la información que necesitamos para crear la paginación: el tamaño de las páginas y la cantidad total de ítems.

Notarás que en lugar de una propiedad input directa he utilizado un setter para interceptar la propiedad input recibida. Eso fue por dos cosas: para redondear el pagesAmount (en caso de que por alguna razón no lo estuviera ya) y también para llenar un Array de números con el pagesAmount.

Ok, entonces ¿por qué necesitamos un Array de números? Para poder renderizar todas las páginas posibles para el usuario. En Angular no podemos tomar directamente un número y pedir un bucle *ngFor una cantidad específica de veces, por lo que es una estrategia que suelo utilizar para superar esto.

Lo que hacemos es: utilizando un array de números, podemos hacer un bucle a través de él y utilizar el índice para recuperar el número que queremos. Dado que lo que queremos es sólo una lista regular de números ordenados, es simple de lograr, como se muestra en el marcado de abajo.

<span
*ngFor="let page of pagesArray; let index = index"
="{ 'active': currentPage === index + 1 }
(click)="setPage(index + 1)"
>
{{ index + 1 }}
</span>

En este marcado estamos renderizando todas las páginas posibles para que el usuario elija. Hemos añadido una ngClass para establecer algún estilo en la página actualmente seleccionada para que el usuario sepa en qué página se encuentra actualmente. Además, hemos insertado una acción click que va a emitir un evento para que el componente padre sepa que la página seleccionada ha cambiado.

Ahora, vamos a añadir también dos flechas para facilitar la vida a nuestros usuarios; una para retroceder una página y otra para avanzar una página. Sin embargo, vamos a ocultar la flecha de la izquierda cuando estemos en la primera página y ocultar la flecha de la derecha cuando estemos en la última página.

¡Pero todavía tenemos un problema aquí! ¿Qué pasa si nuestros itemsAmount son cientos y nuestro pageSize es pequeño? ¿O incluso miles de artículos? Estaríamos renderizando todas las páginas a la vez y tendríamos una usabilidad bastante mala con todos esos números ahí colgados.

Hay algunas soluciones de diseño posibles para este problema, como ocultar las páginas del medio u ocultar las últimas páginas a partir de cierto número. La que voy a mostrar es sencilla de conseguir y creo que puede ser interesante en algunos casos; que es cambiar los números de solo ser impresos a usar un elemento html select con cada página como opción.

Así que, volviendo a nuestro markup, vamos a añadir los siguientes cambios a la parte donde renderizamos nuestros números de página:

Código final

Así que, juntando todas nuestras piezas, este sería el código final para un simple pero eficiente componente de paginación implementado. Recibe un input con el tamaño de las páginas y la cantidad total de ítems y permite al usuario seleccionar qué página quiere ver, disparando un evento indicando la página seleccionada para poder manejar la lógica/peticiones de paginación requeridas.