Todas las entradas

Publicado el 9 de mayo, 2023 en Programación

Como crear un bloque dinámico en Gutenberg

Por Pol Solà
13 minutos de lectura

Este artículo intenta ordenar un poco las ideas de un bloque dinámico de Gutenberg, toda la información que ahora mismo está un poco dispersa, recopilada de lo que me habría gustado saber la primera vez que cree uno, explicado paso a paso.

El nuevo editor para WordPress Gutenberg ha llegado para quedarse, esa es la realidad, poco a poco la comunidad desarrolladora lo va asumiendo y aceptando. También ayuda las mejoras que ha recibido el editor visual propio de WordPress en los últimos tiempos, nada que ver con sus inicios.

De aquí que cada vez haya más desarrolladores/as que han empezado a migrar sus plantillas y extensiones de shortcodes o componentes de otros editores visuales como Elementor y Visual Composer a Gutenberg.

¿Qué es un bloque dinámico?

A diferencia de un bloque normal o estático, un bloque dinámico es aquel que requiere de información de la base de datos para mostrar su contenido.

Un ejemplo fácil de este tipo de bloques es si queremos mostrar las últimas entradas de nuestro blog, un listado de los usuarios registrados o por ejemplo un portafolio creado con un Custom Post (que es el ejemplo que vamos a realizar en este tutorial).

El bloque dinámico nos permite definir lo que queremos mostrar, pero a su vez que este contenido se actualice automáticamente cuando se ha modificado / añadido un nuevo elemento que cumpla sus condiciones

Preparando el entorno

Este tutorial da por hecho que tienes unos conocimientos básicos de WordPress, PHP, Javascript y React (Gutenberg funciona sobre React) y que dispones de un entorno de desarrollo local con una instalación de WordPress activa

Por último vas a necesitar Node.js instalado en tu ordenador para poder ejecutar el script de creación de bloques de WordPress

Creando el plugin para nuestro bloque

En este tutorial damos por sentado que dispones de un tipo de post portfolio que has registrado previamente con register_post_type(), si quieres puedes seguir los mismos pasos cambiando el post_type por el que tú prefieras o por post o page para mostrar las entradas o páginas nativas de WordPress

El primer paso de crear un bloque dinámico es el mismo que un bloque estático, vamos a crear un plugin que contenga todo el código de nuestro bloque.

Para ello utilizaremos la librería que ha creado WordPress para esto mismo

Primero abrimos la terminal de nuestro ordenador y navegamos a la carpeta de plugins de nuestro WordPress

cd wp-content/plugins

Una vez dentro de la carpeta vamos a ejecutar la librería

npx @wordpress/create-block

Confirmamos con Y, esto ejecuta el script en modo interactivo, este nos irá haciendo preguntas sobre la configuración de nuestro plugin y bloque, los pasos son:

  1. El tipo de bloque: Por defecto viene seleccionado estático, pero en este caso elegiremos dinámico
  2. El «slug» del bloque: El identificador único del plugin y a su vez nombre de la carpeta
  3. «Namespace» interno: El identificador único nuestro como autores del bloque
  4. «Display title«: Título del bloque
  5. Descripción del bloque
  6. Icono
  7. Categoría: Donde se mostrará el bloque dentro del listado de bloques disponibles
  8. Deseas customizar el plugin: Ponemos que no

Después de esto dejamos que el script instale todo lo necesario, una vez terminado ya tendremos los archivos disponibles

En nuestro caso hemos llamado al plugin utrans-blocks por lo que en los siguientes pasos cuando veas utrans-blocks debes reemplazarlo por el nombre de tu plugin.

Entramos en la carpeta de nuestro plugin con:

cd utrans-blocks

Y para poder empezar a trabajar arrancamos el proyecto con

npm start

Con todo esto, ya podemos activar nuestro bloque y a añadirlo a una de nuestras páginas

¡Listo! Ahora que ya tenemos nuestro plugin creado, vamos a darle funcionalidades

La estructura de un bloque dinámico de Gutenberg

Todo lo que nos interesa modificar de nuestro bloque se encuentra dentro de la carpeta src, como tenemos el proceso de node arrancado en nuestro terminal, cada vez que hagamos un cambio en esta, el proceso generará los archivos de la build

La principal diferencia de estructura entre un bloque estático y uno dinámico es que este segundo cuenta con un archivo render.php para mostrar el bloque en la parte pública de nuestro sitio web

Mientras que un bloque estático contará con un archivo JavaScript

Añadiendo parámetros al backoffice

Digamos que nuestra idea es crear un porfolio en formato grid y queremos que el usuario pueda configurar el número de proyectos a mostrar y en cuantas columnas

Lo primero que tenemos que hacer es declarar estos dos atributos para nuestro bloque, esto lo haremos dentro del block.json

Debemos añadir un nuevo parámetro dentro del json con los atributos que queremos añadir, por ejemplo:

...
"attributes": {
	"numberOfItems": {
		"type": "number",
		"default": 8
	},
	"columns": {
		"type": "number",
		"default": 4
	}
}

Con estos parámetros le estoy diciendo al bloque que quiero un atributo numérico numberOfItems con valor por defecto 8 y un atributo columns, también numérico, con valor por defecto 4

Mostrado los items del portfolio en el backoffice

Toda la visualización y configuración de la parte del backoffice del bloque se hace dentro del edit.js

De momento vamos a hacer que el bloque recoja nuestros últimos proyectos publicados en el porfolio

Primero añadimos useSelect como dependencia

import { useSelect, useDispatch } from '@wordpress/data';

Después modificamos la función Edit de la siguiente manera

export default function Edit( { attributes } ) {
	const { numberOfItems } = attributes;
	const portfolio = useSelect(
		( select ) => {
			return select( 'core' ).getEntityRecords( 'postType', 'portfolio', {
				'per_page': numberOfItems
			});
		}, 
		[ numberOfItems ]
	);
	console.log(portfolio);
}

Vamos por partes, la función Edit, recibe los atributos que hemos definido previamente en el block.json, de momento solo recogemos el numberOfItems para utilizarlo en el useSelect.

El useSelect, recibe dos parámetros, el primero la función en la que le indicamos que queremos que nos devuelva los tipos de post porfolio, limitados al número de items de numberOfItems

El segundo parámetro es una array de dependencias de las variables que queremos que useSelect tenga en cuenta, que si se modifican requiere que refresque los resultados obtenidos

Ahora añadimos una función .map, para realizar un bucle con los proyectos y mostrarlos

export default function Edit( { attributes } ) {
	const { numberOfItems, columns } = attributes;
	const portfolio = useSelect(
		( select ) => {
			return select( 'core' ).getEntityRecords( 'postType', 'portfolio', {
				'per_page': numberOfItems
			});
		}, 
		[ numberOfItems ]
	);
	return (
		<div { ...useBlockProps() }>
			<ul class="portfolio portfolio-cols--{ columns }">
				{ porfolio && porfolio.map( ( project ) => {
					return (
						<li key={ project.id }>
							<h3>
								<a href={ project.link }>
									{ project.title }
								</a>
							</h3>
						</li>
					)
				})}
			</ul>
		</div>
	);
}

Añadiendo campos para modificar los atributos

Ahora vamos a añadir dos controles para nuestro bloque que nos permita modificar el número de ítems del porfolio a mostrar y el número de columnas.

El número de ítems lo crearemos como un campo de número, mientras que las columnas será un desplegable con opciones cerradas, para ello primero debemos importar los componentes por los tipos de campo necesarios.

Como queremos mostrar estos campos en la barra lateral (InspectorControls), también debemos importar este y los componentes del panel de la siguiente forma

import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, PanelRow, SelectControl, TextControl } from '@wordpress/components';

Ahora vamos a modificar la función Edit para mostrar los dos nuevos campos

export default function Edit( { attributes, setAttributes } ) {
	const { numberOfItems, columns } = attributes;
	const portfolio = useSelect(
		( select ) => {
			return select( 'core' ).getEntityRecords( 'postType', 'portfolio', {
				'per_page': numberOfItems
			});
		}, 
		[ numberOfItems ]
	);
	return (
		<>
		<InspectorControls>
			<PanelBody title={ __( "Portfolio display options", 'utrans-portfolio' ) }>
				<PanelRow>
					<SelectControl
						label={ __( "Number of columns", 'utrans-portfolio' ) }
						value={ attributes.columns }
						options={ [
							{ label: 'One column', value: 1 },
							{ label: 'Two columns', value: 2 },
							{ label: 'Three columns', value: 3 },
							{ label: 'Four columns', value: 4 }
						] }
						onChange={ ( val ) => setAttributes( { operation: val } ) }
						__nextHasNoMarginBottom
					/>
				</PanelRow>
				<PanelRow>
					<TextControl
						label={ __( "Number of items", 'utrans-portfolio' ) }
						onChange={ ( val ) => setAttributes( { number: val } ) }
						type="number"
						min="0"
						value={ attributes.numberOfItems }
					/>
				</PanelRow>
			</PanelBody>
		</InspectorControls>
		<div { ...useBlockProps() }>
			<ul class="portfolio portfolio-cols--{ columns }">
				{ porfolio && porfolio.map( ( project ) => {
					return (
						<li key={ project.id }>
							<h3>
								<a href={ project.link }>
									{ project.title }
								</a>
							</h3>
						</li>
					)
				})}
			</ul>
		</div>
		</>
	);
}

Como podemos ver hemos creado un componente de InspectorControls con un PanelBody y después un PanelRow por cada campo que queramos añadir

En cuanto se modifica un campo se lanza la función setAttribute que guardará el nuevo valor

Con esto listo, vamos a trabajar la parte pública de nuestro bloque

Mostrando nuestro porfolio en la parte pública de nuestra web

En un bloque dinámico, el encargado de renderizar este en la parte pública es el archivo render.php y podemos utilizar todas las funciones de WordPress

Este archivo recibe una variable especial $attributes que dispone del valor de los atributos que hayamos configurado en el editor

Para renderizar los elementos del porfolio vamos a realizar una WP_Query, usando el atributo numberOfItems para definir el número de elementos y el atributo columns para utilizarlo como nombre de clase CSS y poder darle estilos a posteriori

<?php
$number = isset($attributes['numberOfItems']) ? $attributes['numberOfItems'] : 8;
$columns = isset($attributes['columns']) ? $attributes['columns'] : 4;
$args = [
	'post_type' 	 => 'portfolio',
	'posts_per_page' => $number,
];
$the_query = new WP_Query( $args );
?>
<div <?php echo get_block_wrapper_attributes(); ?>>
	<ul class="portfolio portfolio--cols--<?php echo $columns; ?>">
		<?php 
			// The Loop
			if ( $the_query->have_posts() ) {
				while ( $the_query->have_posts() ) {
					$the_query->the_post(); ?>
					<li class="portfolio__item">
						<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a>
					</li>
					<?php
				}
			}
			// Restore original Post Data
			wp_reset_postdata();
		?>
	</ul>
</div>

¿Dónde ponemos los estilos CSS?

Dentro del directorio del bloque encontramos dos archivos de estilos stye.scss y editor.scss

Los estilos que definíamos en el style.scss se cargaran tanto en el editor como en el frontal de la web, mientras que los estilos definidos en el editor.scss solo se cargaran en el editor de Gutenberg

Vemos que la extensión de los archivos es .scss, Node i Webpack se encargan de procesar estos estilos a CSS puro, por lo que podemos escribir nuestro CSS en formato SCSS con todas las ventajas que este incluye, si no estás familiarizado/a con SCSS, haz clic aq

Vamos a añadir algo de estilos a nuestro porfolio

.wp-block-utrans-portfolio-utrans-blocks {
	.portfolio {
		display: grid;
		grid-template-columns: repeat(1, minmax(0, 1fr));
		gap: 1rem;
		&--cols--2 {
			grid-template-columns: repeat(2, minmax(0, 1fr));
		}
		&--cols--3 {
			grid-template-columns: repeat(3, minmax(0, 1fr));
		}
		&--cols--4 {
			grid-template-columns: repeat(4, minmax(0, 1fr));
		}
	}
}

¿Y ahora qué?

Este tutorial pretende ser una introducción a la creación de bloques dinámicos de Gutenberg, puedes ampliar mejorado la visualización de la parte frontal o añadiendo nuevos parámetros de personalización en el editor

Te dejo con algunos enlaces relevantes que me han ayudado en estos primeros pasos:

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

16 − 10 =

Seguir leyendo

Ver todo
blog

¡Posiciónate en la red con un blog!

Pol Solà
febrero 2023 Un minuto de lectura

Las redes sociales, un altavoz corporativo en el Ágora Digital

Pol Solà
mayo 2023 Un minuto de lectura