JavaScript crear paginador | Programador Web Valencia

JavaScript crear paginador

8 minutos

Javascript

Vamos a aprender como paginar datos con JavaScript, haciendo que sea perfectamente configurable por medio de variables como puede ser indicar cuantos elementos por página deseamos imprimir (dibujar). Además estará totalmente automatizado ya que se calculará el número de páginas disponibles y algunas tareas menores como cuando deben habilitarse los controles.

En el ejemplo voy a paginar un JSON que contiene un listado de 10 artículos de un blog. Los mostraremos de 3 en 3. A continuación puedes jugar con una demostración.

Demostración interactiva

HTML

Lo primero que necesitaremos es un lugar en el DOM para dibujar cada artículo de la página.

<!-- Lugar donde generaremos todos los articulos por página -->
<div id="listado-articulos"></div>

Por otro lado, incluiremos los botones para retroceder o avanzar.

<!-- Botón para ir a la página anterior -->
<button id="atras">👈</button>

<!-- Botón para ir a la página siguiente -->
<button id="siguiente">👉</button>

Para que el usuario sepa en que página se encuentra, y cuantas páginas hay disponibles, reservaremos un lugar para mostrar el texto informativo.

<!-- Información de la página actual -->
<span id="informacion-pagina"></span>

Por último, ya que trabajaremos con JavaScript vainilla (sin usar frameworks como React, Vue o Angular), construiremos una plantilla HTML con la estructura de los artículos de cada página.

<!-- Plantilla del artículo -->
<template id="plantilla-articulo">
	<article>
		<h2 id="titulo"></h2>
		<p id="cuerpo"></p>
	</article>
</template>

Todo unido podría tener el siguiente aspecto.

<h1>Paginador</h1>
<section>
    <!-- Lugar donde generaremos todos los articulos por página -->
    <div id="listado-articulos"></div>
    <!-- Controles del paginador -->
    <div>
	<!-- Botón para ir a la página anterior -->
	<button id="atras">👈</button>
	<!-- Información de la página actual -->
	<span id="informacion-pagina"></span>
	<!-- Botón para ir a la página siguiente -->
	<button id="siguiente">👉</button>
    </div>
</section>
<!-- Plantilla del artículo -->
<template id="plantilla-articulo">
    <article>
	<h2 id="titulo"></h2>
	<p id="cuerpo"></p>
    </article>
</template>

Base de datos

Usaremos un Array que contiene 10 JSON con la estructura del artículo. Lo guardaremos en la variable baseDeDatos.

Por supuesto, puedes rellenar la variable con cualquier otro JSON u obtener los datos de una API por medio de una petición AJAX.

[
	{
		 "userId": 1,
		 "id": 1,
		 "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
		 "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
	},
	{
		 "userId": 1,
		 "id": 2,
		 "title": "qui est esse",
		 "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
	},
	{
		 "userId": 1,
		 "id": 3,
		 "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
		 "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
	},
	{
		 "userId": 1,
		 "id": 4,
		 "title": "eum et est occaecati",
		 "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
	},
	{
		 "userId": 1,
		 "id": 5,
		 "title": "nesciunt quas odio",
		 "body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
	},
	{
		 "userId": 1,
		 "id": 6,
		 "title": "dolorem eum magni eos aperiam quia",
		 "body": "ut aspernatur corporis harum nihil quis provident sequi\nmollitia nobis aliquid molestiae\nperspiciatis et ea nemo ab reprehenderit accusantium quas\nvoluptate dolores velit et doloremque molestiae"
	},
	{
		 "userId": 1,
		 "id": 7,
		 "title": "magnam facilis autem",
		 "body": "dolore placeat quibusdam ea quo vitae\nmagni quis enim qui quis quo nemo aut saepe\nquidem repellat excepturi ut quia\nsunt ut sequi eos ea sed quas"
	},
	{
		 "userId": 1,
		 "id": 8,
		 "title": "dolorem dolore est ipsam",
		 "body": "dignissimos aperiam dolorem qui eum\nfacilis quibusdam animi sint suscipit qui sint possimus cum\nquaerat magni maiores excepturi\nipsam ut commodi dolor voluptatum modi aut vitae"
	},
	{
		 "userId": 1,
		 "id": 9,
		 "title": "nesciunt iure omnis dolorem tempora et accusantium",
		 "body": "consectetur animi nesciunt iure dolore\nenim quia ad\nveniam autem ut quam aut nobis\net est aut quod aut provident voluptas autem voluptas"
	},
	{
		 "userId": 1,
		 "id": 10,
		 "title": "optio molestias id quia eum",
		 "body": "quo et expedita modi cum officia vel magni\ndoloribus qui repudiandae\nvero nisi sit\nquos veniam quod sed accusamus veritatis error"
	}
]

JavaScript

Todo se inicia con la última línea: renderizar(). Desencadena diferentes tareas, pero la más destacable sería obtenerRebanadaDeBaseDeDatos(paginaActual), que es la encargada de cortar la información de baseDeDatos y devolvernos un Array con los artículos de la página adecuada. A continuación itera cada elemento, con un forEach, he inserta un nuevo de elemento DOM a partir de la plantilla.

Te recomiendo leer con calma los comentarios. No es complejo su funcionamiento, pero deberías entender todos los pasos si tu intención es modificarlo en cuanto a su diseño o estructura.

// --
// Variables
// --
const listadoArticulosDOM = document.querySelector("#listado-articulos");
const botonAtrasDOM = document.querySelector("#atras");
const informacionPaginaDOM = document.querySelector("#informacion-pagina");
const botonSiguienteDOM = document.querySelector("#siguiente");
const plantillaArticulo = document.querySelector("#plantilla-articulo").content.firstElementChild;
const elementosPorPagina = 3;
let paginaActual = 1;
const baseDeDatos = []; // Todos los datos anterior

// --
// Funciones
// --

/**
 * Función que pasa a la siguiente página
 * @return void
 */
function avanzarPagina() {
	// Incrementar "paginaActual"
	paginaActual = paginaActual + 1;
	// Redibujar
	renderizar();
}

/**
 * Función que retrocedea la página anterior
 * @return void
 */
function retrocederPagina() {
	// Disminuye "paginaActual"
	paginaActual = paginaActual - 1;
	// Redibujar
	renderizar();
}

/**
 * Función que devuelve los datos de la página deseada
 * @param {Int) pagina - Número de página
 * @return {Array<JSON>}
 */
function obtenerRebanadaDeBaseDeDatos(pagina = 1) {
	const corteDeInicio = (paginaActual - 1) * elementosPorPagina;
	const corteDeFinal = corteDeInicio + elementosPorPagina;
	return baseDeDatos.slice(corteDeInicio, corteDeFinal);
}

/**
 * Función que devuelve el número total de páginas disponibles
 * @return {Int}
 */
function obtenerPaginasTotales() {
	return Math.ceil(baseDeDatos.length / elementosPorPagina);
}

/**
 * Función que gestiona los botones del paginador habilitando o
 * desactivando dependiendo de si nos encontramos en la primera
 * página o en la última.
 * @return void
*/
function gestionarBotones() {
	// Comprobar que no se pueda retroceder
	if (paginaActual === 1) {
		botonAtrasDOM.setAttribute("disabled", true);
	} else {
		botonAtrasDOM.removeAttribute("disabled");
	}
	// Comprobar que no se pueda avanzar
	if (paginaActual === obtenerPaginasTotales()) {
		botonSiguienteDOM.setAttribute("disabled", true);
	} else {
		botonSiguienteDOM.removeAttribute("disabled");
	}
}

/**
 * Función que se encarga de dibujar el nuevo DOM a partir de las variables
 * @return void
 */
function renderizar() {
	// Limpiamos los artículos anteriores del DOM
	listadoArticulosDOM.innerHTML = "";
	// Obtenemos los artículos paginados
	const rebanadaDatos = obtenerRebanadaDeBaseDeDatos(paginaActual);
	//// Dibujamos
	// Deshabilitar botones pertinentes (retroceder o avanzar página)
	gestionarBotones();
	// Informar de página actual y páginas disponibles
	informacionPaginaDOM.textContent = `${paginaActual}/${obtenerPaginasTotales()}`;
	// Crear un artículo para cada elemento que se encuentre en la página actual
	rebanadaDatos.forEach(function (datosArticulo) {
		// Clonar la plantilla de artículos
		const miArticulo = plantillaArticulo.cloneNode(true);
		// Rellenamos los datos del nuevo artículo
		const miTitulo = miArticulo.querySelector("#titulo");
		miTitulo.textContent = datosArticulo.title;
		const miCuerpo = miArticulo.querySelector("#cuerpo");
		miCuerpo.textContent = datosArticulo.body;
		// Lo insertamos dentro de "listadoArticulosDOM"
		listadoArticulosDOM.appendChild(miArticulo);
	});
}

// --
// Eventos
// --
botonAtrasDOM.addEventListener("click", retrocederPagina);
botonSiguienteDOM.addEventListener("click", avanzarPagina);

// --
// Inicio
// --
renderizar(); // Mostramos la primera página nada más que carge la página

Resultado final

El siguiente fragmento de código aglutina todo lo mencionado con anterioridad. Esta listo para copiar y pegar.

<!doctype html>
<html lang="es">
    <head>
        <meta charset="UTF-8"/>
        <title>Paginador</title>
    </head>
    <body>
	<h1>Paginador</h1>
	<section>
	    <!-- Lugar donde generaremos todos los articulos por página -->
	    <div id="listado-articulos"></div>
	    <!-- Controles del paginador -->
	    <div>
		<!-- Botón para ir a la página anterior -->
		<button id="atras">👈</button>
		<!-- Información de la página actual -->
		<span id="informacion-pagina"></span>
		<!-- Botón para ir a la página siguiente -->
		<button id="siguiente">👉</button>
	    </div>
	</section>
	<!-- Plantilla del artículo -->
	<template id="plantilla-articulo">
	    <article>
		<h2 id="titulo"></h2>
		<p id="cuerpo"></p>
	    </article>
	</template>

	<script>
	 // --
	 // Variables
	 // --
	 const listadoArticulosDOM = document.querySelector("#listado-articulos");
	 const botonAtrasDOM = document.querySelector("#atras");
	 const informacionPaginaDOM = document.querySelector("#informacion-pagina");
	 const botonSiguienteDOM = document.querySelector("#siguiente");
	 const plantillaArticulo = document.querySelector("#plantilla-articulo").content.firstElementChild;
	 const elementosPorPagina = 3;
	 let paginaActual = 1;
	 const baseDeDatos = [
	     {
		 "userId": 1,
		 "id": 1,
		 "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
		 "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
	     },
	     {
		 "userId": 1,
		 "id": 2,
		 "title": "qui est esse",
		 "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
	     },
	     {
		 "userId": 1,
		 "id": 3,
		 "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
		 "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
	     },
	     {
		 "userId": 1,
		 "id": 4,
		 "title": "eum et est occaecati",
		 "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
	     },
	     {
		 "userId": 1,
		 "id": 5,
		 "title": "nesciunt quas odio",
		 "body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
	     },
	     {
		 "userId": 1,
		 "id": 6,
		 "title": "dolorem eum magni eos aperiam quia",
		 "body": "ut aspernatur corporis harum nihil quis provident sequi\nmollitia nobis aliquid molestiae\nperspiciatis et ea nemo ab reprehenderit accusantium quas\nvoluptate dolores velit et doloremque molestiae"
	     },
	     {
		 "userId": 1,
		 "id": 7,
		 "title": "magnam facilis autem",
		 "body": "dolore placeat quibusdam ea quo vitae\nmagni quis enim qui quis quo nemo aut saepe\nquidem repellat excepturi ut quia\nsunt ut sequi eos ea sed quas"
	     },
	     {
		 "userId": 1,
		 "id": 8,
		 "title": "dolorem dolore est ipsam",
		 "body": "dignissimos aperiam dolorem qui eum\nfacilis quibusdam animi sint suscipit qui sint possimus cum\nquaerat magni maiores excepturi\nipsam ut commodi dolor voluptatum modi aut vitae"
	     },
	     {
		 "userId": 1,
		 "id": 9,
		 "title": "nesciunt iure omnis dolorem tempora et accusantium",
		 "body": "consectetur animi nesciunt iure dolore\nenim quia ad\nveniam autem ut quam aut nobis\net est aut quod aut provident voluptas autem voluptas"
	     },
	     {
		 "userId": 1,
		 "id": 10,
		 "title": "optio molestias id quia eum",
		 "body": "quo et expedita modi cum officia vel magni\ndoloribus qui repudiandae\nvero nisi sit\nquos veniam quod sed accusamus veritatis error"
	     }
	 ];

	 // --
	 // Funciones
	 // --

	 /**
	  * Función que pasa a la siguiente página
	  * @return void
	  */
	 function avanzarPagina() {
	     // Incrementar "paginaActual"
	     paginaActual = paginaActual + 1;
	     // Redibujar
	     renderizar();
	 }

	 /**
	  * Función que retrocedea la página anterior
	  * @return void
	  */
	 function retrocederPagina() {
	     // Disminuye "paginaActual"
	     paginaActual = paginaActual - 1;
	     // Redibujar
	     renderizar();
	 }

	 /**
	  * Función que devuelve los datos de la página deseada
	  * @param {Int) pagina - Número de página
	  * @return {Array<JSON>}
	  */
	 function obtenerRebanadaDeBaseDeDatos(pagina = 1) {
	     const corteDeInicio = (paginaActual - 1) * elementosPorPagina;
	     const corteDeFinal = corteDeInicio + elementosPorPagina;
	     return baseDeDatos.slice(corteDeInicio, corteDeFinal);
	 }

	 /**
	  * Función que devuelve el número total de páginas disponibles
	  * @return {Int}
	  */
	 function obtenerPaginasTotales() {
	     return Math.ceil(baseDeDatos.length / elementosPorPagina);
	 }

	 /**
	  * Función que gestiona los botones del paginador habilitando o
	  * desactivando dependiendo de si nos encontramos en la primera
	  * página o en la última.
	  * @return void
	  */
	 function gestionarBotones() {
	     // Comprobar que no se pueda retroceder
	     if (paginaActual === 1) {
		 botonAtrasDOM.setAttribute("disabled", true);
	     } else {
		 botonAtrasDOM.removeAttribute("disabled");
	     }
	     // Comprobar que no se pueda avanzar
	     if (paginaActual === obtenerPaginasTotales()) {
		 botonSiguienteDOM.setAttribute("disabled", true);
	     } else {
		 botonSiguienteDOM.removeAttribute("disabled");
	     }
	 }

	 /**
	  * Función que se encarga de dibujar el nuevo DOM a partir de las variables
	  * @return void
	  */
	 function renderizar() {
	     // Limpiamos los artículos anteriores del DOM
	     listadoArticulosDOM.innerHTML = "";
	     // Obtenemos los artículos paginados
	     const rebanadaDatos = obtenerRebanadaDeBaseDeDatos(paginaActual);
	     //// Dibujamos
	     // Deshabilitar botones pertinentes (retroceder o avanzar página)
	     gestionarBotones();
	     // Informar de página actual y páginas disponibles
	     informacionPaginaDOM.textContent = `${paginaActual}/${obtenerPaginasTotales()}`;
	     // Crear un artículo para cada elemento que se encuentre en la página actual
	     rebanadaDatos.forEach(function (datosArticulo) {
		   // Clonar la plantilla de artículos
		   const miArticulo = plantillaArticulo.cloneNode(true);
		   // Rellenamos los datos del nuevo artículo
		   const miTitulo = miArticulo.querySelector("#titulo");
		   miTitulo.textContent = datosArticulo.title;
		   const miCuerpo = miArticulo.querySelector("#cuerpo");
		   miCuerpo.textContent = datosArticulo.body;
		   // Lo insertamos dentro de "listadoArticulosDOM"
		   listadoArticulosDOM.appendChild(miArticulo);
	     });
	 }

	 // --
	 // Eventos
	 // --
	 botonAtrasDOM.addEventListener("click", retrocederPagina);
	 botonSiguienteDOM.addEventListener("click", avanzarPagina);

	 // --
	 // Inicio
	 // --
	 renderizar(); // Mostramos la primera página nada más que carge la página

	</script>
    </body>
</html>

Si tu intención es crear un paginador infinito, que se rendericen los datos según se realiza scroll hacia abajo, te recomiendo leer el siguiente artículo donde continúo el artículo.

Esta obra está bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivadas 4.0 Internacional.

Atribución/Reconocimiento-NoComercial-SinDerivados 4.0 Internacional

¿Me ayudas?

Comprame un café
Pulsa sobre la imagen

No te sientas obligado a realizar una donación, pero cada aportación mantiene el sitio en activo logrando que continúe existiendo y sea accesible para otras personas. Además me motiva a crear nuevo contenido.

Comentarios

{{ comments.length }} comentarios

Nuevo comentario

Nueva replica  {{ formatEllipsisAuthor(replyComment.author) }}

Acepto la política de Protección de Datos.

Escribe el primer comentario

Tal vez también te interese...