Creando una tabla paginada con back-end (server-side) en Angular

En este tutorial te enseño cómo hacer una tabla paginada obteniendo los datos desde un API o back-end de forma fácil con Angular.

Advertencia: Esta publicación considera que ya tienes un back-end en Laravel con paginación implementada, si no utilizas Laravel y tienes otros como NodeJS solamente debes considerar la respuesta del servidor para que haga empate con los requerimientos de la paginación.

Normalmente me gusta trabajar con tablas simples como la de ng-datatable (https://www.npmjs.com/package/@pascalhonegger/ng-datatable) que me permite ordenar y paginar dentro de la dependencia de forma muy simple y puedo así traer mucha información desde el back-end, sin embargo puede haber casos donde estemos hablando de muuuuy altas cantidades dígase por ejemplo 5 millones de registros, obviamente no vamos a mostrar esos 5 millones de jalón.

Así que tomando como premisa este punto, me puse a investigar bastante acerca de qué opciones tenía como PrimeNG, Mat-Table, la vieja Datatables con jQuery y demás, sin embargo, Mat-Tables necesita cargar las dependencias de Angular Material y como manejo sistemas diseñados a la medida (respecto a estilos) cargar Angular Material no era opción, PrimeNG tampoco lo fue, usar jQuery en Angular es una malísima práctica y Datatables no maneja el VDOM así que es horrible trabajar con ella en Angular, entre muchas otras así que decidí trabajar con una dependencia llamada ngx-pagination (https://www.npmjs.com/package/ngx-pagination) y desarrollar mi propia tabla con esta para apoyarme…

¿Por qué decidí apoyarme con ngx-pagination ? porque tiene cierto soporte de paginación con server-side (es decir que el back-end tiene la paginación implementada)

Bueno, ya teniendo el contexto como de costumbre, vamos a empezar a programar.

Lo primero que necesitamos es entender que en este caso únicamente vamos a considerar la paginación, si esta publicación se hace popular, incluiré un sistema para cambiar el límite a mostrar y el orden de la información.

Bueno, vamos a instalar el ngx-pagination con:

npm i ngx-pagination

Una vez que se instale hay que cargarlo como indica la documentación en el módulo donde lo usaremos, en este ejemplo pensaremos que será el app.module :

// app.module.ts
...
import {NgxPaginationModule} from 'ngx-pagination';
...
@NgModule({
...
 imports: [
  ...
  NgxPaginationModule
  ...
 ],
...
})

Ya que lo tenemos cargado, vamos a poder utilizarlo.

Ahora, hay que traer la data en la tabla. Para ello en nuestro componente, vamos a generar algunas variables primero:

data = [];
page = 1;
total = 0;
perPage = 10;

La primera es la variable que contiene nuestra información, la segunda la página en la que nos encontramos, la tercera el total de datos totales en la base de datos (por así decirlo ya que se inicializa en 0 pero después en la llamada sabremos cuál es el total) y la última para que la paginación sepa cuántos elementos se van a mostrar. Gran parte de estas variables sirve para cálculos de ngx-pagination

Vamos a importar OnInit y las dependencias del sistema de routing de Angular con algo como:

import {ActivatedRoute, Params, Router} from '@angular/router';

Y vamos a cargarlas internamente.

export class TableComponent implements OnInit {
...
constructor(... private route: ActivatedRoute, private router: Router ...) {
...

Una vez que tenemos ya cargadas todas nuestras dependencias, manos a la obra con dos funciones, la primera será aquella que maneje la obtención de datos y la segunda el cambio de página.

Para ello, la primera haremos uso de un servicio, en este caso no explicaré cómo obtener los datos, pero, pensaré que ya tienen su servicio para obtener datos de un API ya que este tutorial se basa en la tabla únicamente:

getData(page: number = 1) {
  this.tableService.getAll(page).subscribe(response => {
    this.data = response.data.table;
    this.total = response.pagination.total;
  });
}

Entonces, ¿qué hace esta función?, a través del parámetro “page” sabremos qué página estamos. Internamente, Laravel en su sistema de paginación nos permite mandarnos ciertos datos en su response, en este caso, yo retorno la información de la siguiente forma por ejemplo:

{ data: [{ id: 1 }, { id: 2 }...], pagination: { per_page: 10, total: 200, ... }, status: 200}

Entonces de esta forma, Laravel nos facilita muchísimo el trabajo. Claro, ustedes pueden modificar el response a su gusto, en este caso, pensamos que así viene la respuesta. ¿Pero qué necesitamos realmente?, para este tutorial ocupamos que el back-end nos retorne pagination.total donde total es toda la cantidad de datos que hay en back-end, básicamente aquí pueden seleccionar por ejemplo un count(*) o el último ID de la tabla si es un caso donde no se haga soft-delete (es decir, no se borran realmente los datos solo se “ocultan” por así decirlo).

Asimismo, en la parte de la función, Laravel por default nos permite mandarle el dato ?page=xxxx donde xxxx es un numérico y Laravel se encargará de hacer la paginación, en caso de que decidan hacer uso de otro sistema, deberán tener en cuenta este dato.

Retomando entonces, la función hará una petición a una URL tipo:

https://api.mipagina.com/api/v1/tabla?page=xxxx

Donde en nuestro servicio la función que llamamos previamente en getData se vería más o menos así:

public getAll(page: number = 1): Observable<any> {
  return this.apiService.get('https://api.mipagina.com/api/v1/tabla' + '?page=' + page);
}

Ya tenemos la obtención de datos en el componente, en el servicio, nuestras variables y nuestras importaciones, ¿qué sigue?.

Ahora, vamos a generar la segunda función que les mencionaba para cuando cambiamos de página:

pageChanged(page) {
  this.page = page;
  const queryParams: Params = {page};
  this.router.navigate(
    [],
    {
      relativeTo: this.route,
      queryParams
    }
  );
  this.getData(this.page);
}

En este caso lo que hará es que “reasignará” la URL y obtendrá la información usando la nueva página.

Hasta aquí ya tenemos la obtención de datos del back-end, la paginación a nivel de lógica y solo nos faltan dos detalles, la tabla como tal en el HTML y un sistema que nos permita leer el parámetro de la página una vez que cambiamos entre estas usando la función previamente mencionada. Para ello, en nuestro ngOnInit vamos a integrar el siguiente código:

this.route.queryParams.subscribe(params => {
  this.page = parseInt(params.page, 10) || 1;
  this.getData(this.page);
  window.scrollTo(0, 0);
});

¿Qué hace este código?, bueno, vamos a estar observando cambios en los parámetros tipo “consulta” (en inglés se conocen como Query Parameters ) que en las URLs las vemos como midato=true&id=123&page=hola . Si un dato en los parámetros cambia, lo reasignamos y recargamos la información. Vamos a revisar que siempre sea un entero con la finalidad que si alguien pone por ejemplo ?page=a al ser a una string, no hará match parseInt y pues entonces, asignaremos 1 por default. Otra comprobación que se puede hacer es que page no sea menor a 1, pero esto, se los dejo a ustedes.

Para finalizar, el window.scrollTo nos permitirá subir hasta el tope del sitio para empezar a revisar la nueva información (esto es algo extra).

Listo, ahora solo nos falta, el HTML…

Para la tabla, vamos a tomar en consideración solo 1 columna al ser una demo, así como todos los datos asignados desde el back-end, para ello entonces tendremos un HTML como el siguiente:

<table>
 <thead>
  <tr>
    <th>ID</th>
  </tr>
 </thead>
 <tbody>
  <tr
    *ngFor="let item of data | paginate: { itemsPerPage: perPage, currentPage: page, totalItems: total }">
    <td>{{item.id}}</td>
  </tr>
 </tbody>
 <tfoot>
  <tr>
    <td>
      <pagination-controls
        [previousLabel]="'Anterior'"
        [nextLabel]="'Siguiente'"
        (pageChange)="pageChanged($event)"></pagination-controls>
    </td>
  </tr>
 </tfoot>
</table>

¿Qué hace este fragmento de código?, bueno, primero en nuestro thead asignamos la cabecera ID para la columna mencionada. Después en el cuerpo de la tabla vamos a mostrar la información, ngx-pagination nos ofrece un pipe con el cual sabrá qué cantidad de datos hay, cuántos se mostrarán para hacer cálculos y en qué página se encuentra para mostrar el active en la paginación (estilos y esas cosas…)

Por último en el pie de la tabla, tendremos los controles, en este caso usaré los labels de Anterior y Siguiente y para finalizar, la parte relevante, cada vez que cambiemos de página, ngx-pagination ejecutará nuestra función previamente creada y nos hará saber en qué página estamos ahora.

Como mencionaba previamente, cada vez que cambiemos de página el Query Parameter (parámetro de consulta o como quieran decirle) cambiará y recargaremos la info con la nueva obtenida desde el back-end.

¡Y eso es todo!. Ya tenemos una tabla paginada con back-end de forma simple.

¿Cuál es tu reacción?
+1
0
+1
0
+1
0
+1
0
+1
1
Total
0
Shares
Publicación anterior

Cómo integrar Google Maps en Angular de forma sencilla

Siguiente Publicación

Manejando roles y permisos en Angular

Publicaciones Relacionadas