Normalmente en el trabajo, usamos plantillas “multiuso” de estas que traen ya el típico page builder con sus columnitas y mil quinientos treinta y tres modulitos (lo odio bastante porque nunca encuentro las opciones que quiero y al final cuando las encuentro no hacen lo que necesito…).
No he tenido la posibilidad de usar mucho el editor Gutenberg con los nuevos bloques, y quería experimentar un poquito… y justo he visto un tutorial “migran” el código de un shortcode a un block. Así que vamos a ello. El tutorial en cuestión es https://learn.wordpress.org/lesson/using-block-attributes-to-enable-user-editing/ y es gratuito.
Voy a ir escribiendo según voy probando cosas.
Vamos a usar Create Block Tool para crear nuestro primer block. Conseguiremos tener lo mismo que con un shortcode, pero integrado en el editor de WordPress con sus opciones. Esto es una gran herramienta para personalizaciones, por ejemplo si tenemos un shortcode que nos saca las típicas valoraciones con estrellitas que hayamos hecho nosotros (o cualquier otro shortcode “pequeño” que usemos para introducir un elemento de contenido), podremos tener lo mismo pero con una interfaz directamente en el admin sin tener que estar recordando las opciones del shortcode o cómo se usaba.
Lo que más me interesa es poder editar las opciones desde el sidebar (el Settings Sidebar) donde podemos configurar el block… porque siempre que hago un shortcode, he de documentar qué parámetros usa y cómo. No hay una guía visual como este Settings Sidebar con un listadito de qué cosas se pueden configurar.
Empezaremos teniendo una instalación de WordPress en local, con Node.
Introducción a Create Block Tool
Es una herramienta de línea de comandos que nos dará todo lo necesario para crear un block y por supuesto utilizaremos de base para copiar y pegar o simplemente de referencia para modificar nuestro shortcode a block.
Requerimientos
En su página oficial vemos como requisitos: requires node version 14.0.0 or above, and npm version 6.14.4 or above. A fecha de esta prueba tengo Node v18.12.1 y npm v8.19.2 instalado por defecto en Devilbox.
Ejemplo básico
Nos vamos al directorio wp-plugins y ejecutamos create-block-tool de forma básica:
cd wp-content/plugins
npx @wordpress/create-block wp-learn-todo
Nos pedirá instalar unos paquetes y al final nos creará lo siguiente:
- build – sitio final de los ficheros para su distribución
- node_modules – paquetes de node para desarrollo
- src – aquí es donde estará el código que iremos desarrollando
- package.json – dependencias de nuestro código
- readme.txt – se usa en el repositorio de WordPress.org
- wp-learn-todo.php – fichero principal que indica a WordPress que se trata de un plugin
En este punto podemos entrar al admin y activar el plugin. Con lo que ya tendremos un simple “block” que de momento es un párrafo (insertamos el block “/learn” en el editor).
Desde un shortcode
Vamos a partir de un plugin que simplemente nos registre un shortcode que de manera muy escueta imprima un html, sin nada más complejo.
Plugin de base
Siguiendo el tutorial que estoy viendo para esto, creamos en wp-content/plugins el wp-learn-subscribe/wp-learn-subscribe.php con este contenido:
<?php
/**
* Plugin Name: WP Learn Subscribe
* Description: Using a shortcode, render a subscribe area anywhere on your site
* Version: 1.0.0
* Text Domain: wp-subscribe
* License: GPLv2 or later
*
* @package WP_Learn_Subscribe
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_shortcode( 'wp-subscribe', 'wps_subscribe_shortcode' );
function wps_subscribe_shortcode() {
ob_start();
?>
<div class="wp-subscribe-subscribe">
<h2>Subscribe!</h2>
<p>Visit our <a href="/subscribe">subscribe page</a> and sign up to get notified</p>
</div>
<?php
return ob_get_clean();
}
Una vez instalado, lo usamos en un editor de texto:
[wp-subscribe]
Aquí esperaba yo que en el tutorial, pusieran un shortcode que acepta parámetros y acabes usando algo similar a:
[wp-subscribe heading="Subscribe"]
Pero no… De todas formas es muy sencillo. Dejo aquí el link con la explicación: https://developer.wordpress.org/plugins/shortcodes/shortcodes-with-parameters/
Preparar plugin para usar blocks
Desde el directorio del plugin, crearemos el fichero package.json
npm init
Podemos dejar todo por defecto, pero se recomienda cambiar la licencia a GPL-2.0-or-later cuando el asistente del CLI nos pregunte.
Dependencias básicas
npm install @wordpress/scripts --save-dev
Configuraciones para @wordpress/scripts
En https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/ encontraremos el fragmento scripts para actualizar nuestro package.json que será el siguiente:
"scripts": {
"build": "wp-scripts build",
"check-engines": "wp-scripts check-engines",
"check-licenses": "wp-scripts check-licenses",
"format": "wp-scripts format",
"lint:css": "wp-scripts lint-style",
"lint:js": "wp-scripts lint-js",
"lint:md:docs": "wp-scripts lint-md-docs",
"lint:pkg-json": "wp-scripts lint-pkg-json",
"packages-update": "wp-scripts packages-update",
"plugin-zip": "wp-scripts plugin-zip",
"start": "wp-scripts start",
"test:e2e": "wp-scripts test-e2e",
"test:unit": "wp-scripts test-unit-js"
}
También cambiamos el entry point al index que estará en el directorio build
"main": "build/index.js",
Registrar block y crear fichero en src
Desde el fichero principal del plugin, registramos el block:
/**
* Registers the block using the metadata loaded from the `block.json` file.
* Behind the scenes, it registers also all assets so they can be enqueued
* through the block editor in the corresponding context.
*
* @see https://developer.wordpress.org/reference/functions/register_block_type/
*/
add_action( 'init', 'wpl_subscribe_block_init' );
function wpl_subscribe_block_init() {
register_block_type( __DIR__ . '/build' );
}
Creamos ficheros de src
Podemos copiarlos del plugin de ejemplo con create block tool, simplemente copiamos todo el directorio src en nuestro plugin y modificamos lo siguiente:
- block.json:
- el name debe cuadrar nuestros nuevo plugin con estructura recomendada de SLUG/MAIN-FILE (de esta forma wp-learn-subscribe/wp-learn-subscribe-block)
- title y description a algo más descriptivo y acorde al plugin actual
- text-domain a wp-learn-subscribe
En este punto podemos arranacar el servidor de desarrollo de @wordpress/scripts para evitar tener que hacer build del código en cada cambio, ya que este servidor estará escuchando a cambios en los ficheros y lanzará un build automáticamente. Para ello:
npm start
Cada vez que queramos volver al desarrollo de nuestro plugin, hemos de entrar al directorio del plugin y ejecutar npm start.
Actualizar ficheros edit.js y save.js
Aquí simplemente copiamos con cuidado el html resultante de nuestro shortcode al retorno de la función Edit y Save respectivamente de cada fichero, en JSX y sustituir la clase del div principal a …useBlockProps.save() para el save.js y …useBlockProps() para el edit.js
Estos ficheros contendrán lógica más compleja, pero de momento como ejemplo simplemente deben devolver el html final y usar el useBlockProps adecuado.
El edit.js quedaría así:
// ...
export default function Edit() {
return (
<div { ...useBlockProps() }>
<h2>Subscribe!</h2>
<p>Visit our <a href="/subscribe">subscribe page</a> and sign up to get notified</p>
</div>
);
}
// ...
El save.js quedaría así:
// ...
export default function Edit() {
return (
<div { ...useBlockProps.save() }>
<h2>Subscribe!</h2>
<p>Visit our <a href="/subscribe">subscribe page</a> and sign up to get notified</p>
</div>
);
}
// ...
Ahora ya podemos probar de crear un block en el editor con subscribe.
Dar estilos al block
Estilos de un shortcode
Normalmente, en un plugin que usa shortcodes hacemos lo siguiente (todo puede estar en el fichero principal del plugin). Primero registramos los estilos:
define( 'WPL_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
add_action('wp_enqueue_scripts', 'wpl_subscribe_shortcode_scripts');
function wpl_subscribe_shortcode_scripts() {
wp_register_style('wpl-subscribe-style', WPL_PLUGIN_URL . 'assets/css/style.css', array(), '1.0.0');
}
Y luego llamamos a estos estilos registrados dentro de la función del shortcode para que se carguen los ficheros css cuando se use el shortcode ():
add_shortcode( 'wp-subscribe', 'wpl_subscribe_shortcode' );
function wpl_subscribe_shortcode() {
wp_enqueue_style( 'wpl-subscribe-style' );
ob_start();
?>
<div class="wpl-subscribe-subscribe">
<h2 class="subscribe-header">Subscribe!</h2>
<p>Visit our <a href="/subscribe">subscribe page</a> and sign up to get notified</p>
</div>
<?php
return ob_get_clean();
}
Nota: la única línea cambiada es wp_enqueue_style( ‘wpl-subscribe-style’ );
Estilos de un block
En el fichero block.json vemos que tenemos dos hojas de estilo definidas:
//...
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
//...
El fichero de “style” se cargará siempre que el bloque se utilice, tanto en el front como en el back.
Sin embargo el fichero de “editorstyle” solo se cargará en el back, permitiéndonos dar estilos específicos para campos que solo se rendericen en el editor del backend.
Estos archivos provienen del direcotorio src y son los que hemos de modificar:
- src/style.scss se compilará en style-index.css
- src/editor.scss se compilará en index.css
El servidor virtual arrancado con npm start ya mirará cambios en estos ficheros e iniciará el proceso de build cada vez que modifiquemos alguno.
Al usar useBlockProps() como clase en el JSX de nuestro block, nos añade una clase concreta basada en nuestro plugin. En este caso es “.wp-block-wp-learn-subscribe-wp-learn-subscribe-block” que usaremos para dar estilos.
Editar el bloque usando atributos
Habilitar el uso de atributos
Para usar atributos y que podamos editar el block desde el admin en lugar de sacar solo el html con valores fijos, primero hemos de habilitarlo en block.json que le añadimos:
...
"attributes": {
"heading": {
"type": "string",
"default": "Subscribe!"
}
},
...
Ahora podremos acceder a las React props en los componentes Edit y Save. En estas funciones se reciben los atributos como parámetros, que si los imprimimos en la consola veremos dos propiedades que usaremos: attributes y setAttributes(). Para ello en edit.js añadimos:
export default function Edit( blockProps ) {
console.log( blockProps )
...
y si desestructuramos el objeto, podremos acceder a dicha propiedad directamente. La función quedaría así finalmente:
export default function Edit( {attributes} ) {
return (
<div {...useBlockProps()}>
<h2 className={"subscribe-header"}>{attributes.heading}</h2>
<p>Visit our <a href="/subscribe">subscribe page</a> and sign up to get notified</p>
</div>
);
}
Habilitar el editado de atributos usando la Settings Sidebar
Primero hemos de incluir algunos paquetes. Podemos revisar la guía entera aqui https://developer.wordpress.org/block-editor/reference-guides/packages/
Actualizamos el import del block-editor y añadimos un import más debajo en edit.js:
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { Panel, PanelBody, TextControl } from '@wordpress/components';
Y actualizamos el la función Edit para que el return de JSX devuelva varios componentes anidados (Panel > PanelBody > TextControl. Cuidado, dentro del div con …useBlockProps y sin quitar nada de lo que ya hay, añadimos dentro:
<div {...useBlockProps()}>
<InspectorControls key="setting">
<Panel>
<PanelBody title="Subscribe attributes" initialOpen={true}>
<TextControl className="blocks-base-control__input"
label={"Heading"}
value={attributes.heading}
onChange={(val) => setAttributes({heading: val})}
/>
</PanelBody>
</Panel>
</InspectorControls>
<h2 className={"subscribe-header"}>{attributes.heading}</h2>
<p>Visit our <a href="/subscribe">subscribe page</a> and sign up to get notified</p>
</div>
Lo importante es que:
- el value del componente TextEditor lo ponemos a attributes.heading
- en el onChange guardaremos el valor del atributo, modificando la propiedad attributes a través de la función setAttributes (más adelante, guardaremos el nuevo objeto attributes que contiene los valores modificados por el usuario)
Y hemos de recibir como parámetro de la función también a setAttributes, quedando así:
export default function Edit( {attributes, setAttributes} ) {
Guardar los atributos
Realizamos los mismos cambios o muy similares en save.js.
Incluimos attributes como parametro y usamos attributes.heading para sacar el valor del atributo. El objetoattributes ya contiene los valores que hemos seteado desde el componente TextEditor en el componente Edit.
export default function save( {attributes} ) {
return (
<div {...useBlockProps.save()}>
<h2 className={"subscribe-header"}>{attributes.heading}</h2>
<p>Visit our <a href="/subscribe">subscribe page</a> and sign up to get notified</p>
</div>
);
}
Y si guardamos la entrada, el bloque se guarda correctamente con lo que editemos desde el Settings Sidebar.