shortcodes to blocks

Deja a un lado los shortcodes y crea bloques

Con el refactor que hice para darle un lavado de cara al blog, decidí transformar un par de shortcodes que utilizaba en bloques, para pasar de esto:

Shortcode Block

A esto otro:

Notepanel Block

Mucho más intuitivo, ¿no?. Al ser un bloque puedo tener disponibles los atributos de mi shortcode para establecerles los valores que yo quiera. Esto evita que tenga que aprenderme de memoria los atributos que puedo utilizar, y evito posibles problemas de misspelling a la hora de escribir el shortcode.

Hace un tiempo escribí una entrada donde hablaba sobre qué son los shortcodes y cómo crearlos. Voy a utilizar el mismo ejemplo que en su día, para convertir ese Shortcode en un bloque.

Creando un bloque en lugar de un shortcode

La principal diferencia entre generar un shortcode o crear un bloque, radica en que vamos a necesitar encolar al menos un JavaScript. También podremos añadir un CSS propio, para dotar de estilo al bloque en el editor.

Vamos con el ejemplo:

function notepanel_block() {
    wp_register_script( 'notepanel', plugin_dir_url( __FILE__ ) . 'assets/js/notepanel.js', [
        'wp-blocks',
        'wp-i18n',
        'wp-element',
        'wp-components',
        'wp-editor',
    ] );

    wp_register_style(
        'notepanel',
        plugin_dir_url( __FILE__ ) . 'assets/css/notepanel.css',
        [ 'wp-edit-blocks' ]
    );

    register_block_type( 'dwp/notepanel', [
        'editor_script'   => 'notepanel',
        'editor_style'    => 'notepanel',
        'attributes'      => [
            'title'       => [
                'type' => 'string', // null, boolean, object, array, number, string, integer.
            ],
            'description' => [
                'type' => 'string',
            ],
            'type'        => [
                'type' => 'array',
            ],
        ],
    ] );
}

add_action( 'init', 'notepanel_block' );

Como puedes ver, enganchamos el método notepanel_block al hook init. Aquí simplemente registramos un script (notepanel) con una serie de dependencias. También registramos un style (notepanel).

Por último registramos un bloque con la función register_block_type. El primer parámetro que pasamos es el namespace que vamos a dar a nuestro bloque. A continuación indicamos qué JS y qué CSS vamos a encolar en el editor («en el back»). Podríamos crear JS y CSS también para el front, pero como en este ejemplo nos basábamos en un shortcode para crear panels de bootstrap, tendrías que encolar bootstrap o tu tema llevarlo incorporado.

Por último registramos una serie de atributos, al igual que hacíamos para el shortcode. En este ejemplo, añadiremos title para poder establecer el título del panel, description para poder configurar el texto del panel y el type para elegir entre los diferentes tipos de panels (danger, info, warning, success…).

Veamos a continuación qué tendrían los archivos CSS y JS:

.panel {
  margin-bottom: 2em;
  background-color: #ffffff;
  border: 1px solid transparent;
  border-radius: 4px;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
}
.panel .panel-heading {
  padding: 1em;
  border-bottom: 1px solid transparent;
  border-top-right-radius: 3px;
  border-top-left-radius: 3px;
}
.panel .panel-heading .panel-title {
  font-size: 1.125em;
  color: inherit;
  margin-top: 0;
  margin-bottom: 0;
}
.panel .panel-body {
  padding: 1em;
}
.panel .panel-body:before, .panel .panel-body:after {
  content: " ";
  display: table;
}
.panel .panel-body p {
  font-size: 1em;
  margin: 0;
}
.panel.panel-primary {
  border-color: #337ab7;
}
.panel.panel-primary .panel-heading {
  color: #ffffff;
  background-color: #337ab7;
  border-color: #337ab7;
}
.panel.panel-success {
  border-color: #d6e9c6;
}
.panel.panel-success .panel-heading {
  color: #3c763d;
  background-color: #dff0d8;
  border-color: #d6e9c6;
}
.panel.panel-info {
  border-color: #bce8f1;
}
.panel.panel-info .panel-heading {
  color: #31708f;
  background-color: #d9edf7;
  border-color: #bce8f1;
}
.panel.panel-warning {
  border-color: #faebcc;
}
.panel.panel-warning .panel-heading {
  color: #8a6d3b;
  background-color: #fcf8e3;
  border-color: #faebcc;
}
.panel.panel-danger {
  border-color: #ebccd1;
}
.panel.panel-danger .panel-heading {
  color: #a94442;
  background-color: #f2dede;
  border-color: #ebccd1;
}

En el CSS no me voy a detener, básicamente es la parte de CSS de Bootstrap para los panels.

const {registerBlockType} = wp.blocks;
const {InspectorControls} = wp.editor;
const {PanelBody, SelectControl, TextControl, TextareaControl} = wp.components;

registerBlockType('dwp/notepanel', {
    title: 'bloquetitulo',
    description: 'esto era un shortcode',
    icon: 'smiley',
    category: 'common',
    attributes: {
        title: {type: 'string'},
        description: {type: 'string'},
        type: {type: 'string', default: 'success'}
    },
    edit: ({attributes, setAttributes}) => {
        function setTitle(value) {
            setAttributes({title: value});
        }

        function setDescription(value) {
            setAttributes({description: value});
        }

        function setType(value) {
            setAttributes({type: value});
        }

        return wp.element.createElement(
            'div',
            {
                class: 'panel panel-' + attributes.type,
            },
            wp.element.createElement(
                'div',
                {
                    class: 'panel-heading',
                },
                wp.element.createElement(
                    'h3',
                    {
                        class: 'panel-title',
                    },
                    attributes.title
                ),
            ),
            wp.element.createElement(
                'div',
                {
                    class: 'panel-body',
                },
                wp.element.createElement(
                    'p',
                    null,
                    attributes.description
                ),
            ),
            //Block inspector
            wp.element.createElement(
                InspectorControls,
                null,
                wp.element.createElement(
                    PanelBody,
                    null,
                    wp.element.createElement(SelectControl, {
                        value: attributes.type,
                        label: 'Select type',
                        options: [
                            {label: 'primary', value: 'primary'},
                            {label: 'success', value: 'success'},
                            {label: 'info', value: 'info'},
                            {label: 'warning', value: 'warning'},
                            {label: 'danger', value: 'danger'},
                        ],
                        onChange: setType,
                    }),
                    wp.element.createElement(TextControl, {
                        value: attributes.title,
                        label: 'Título',
                        onChange: setTitle,
                    }),
                    wp.element.createElement(TextareaControl, {
                        value: attributes.description,
                        label: 'Description',
                        onChange: setDescription,
                    }),
                )
            ),
        );
    },
    save: ({attributes}) => {
        return wp.element.createElement(
            'div',
            {
                className: 'panel panel-' + attributes.type,
            },
            wp.element.createElement(
                'div',
                {
                    className: 'panel-heading',
                },
                wp.element.createElement(
                    'h3',
                    {
                        className: 'panel-title',
                    },
                    attributes.title
                ),
            ),
            wp.element.createElement(
                'div',
                {
                    className: 'panel-body',
                },
                wp.element.createElement(
                    'p',
                    null,
                    attributes.description
                ),
            )
        );
    }
});

Voy a intentar desgranar parte por parte qué hace cada cachito de código. En primer lugar se declaran unas constantes con los componentes del editor de bloques que vamos a necesitar.

A continuación, registramos el bloque, con el mismo namespace que utilizamos en la parte de PHP, y definimos una serie de atributos:

  • title: Título o Nombre de tu bloque
  • description: Descripción corta de tu bloque
  • icon: El icono que aparecerá en la librería de bloques. Puedes utilizar los dashicons
  • category: Categoría en la que quieres que aparezca tu bloque (comunes, formatos, widgets…)
  • attributes: Lo mismo que declaramos en la parte de PHP, los atributos que un usuario podrá configurar
  • edit: En esta parte se define lo que ocurre en el editor (back). Básicamente creas el HTML (los elementos, tags y atributos) que se pueden visualizar en el bloque.
  • save: En esta parte se define lo que ocurre en el front. Se construye el HTML que se va a pintar cuando se utilice este bloque.

De este modo, ya aparece nuestro bloque en el editor:

notepanel block

Las principales ventajas son que podemos ver cómo quedará en nuestra página, cuando estamos trabajando en ella, y que no es necesario conocer los atributos del shortcode de antemano, ya tenemos disponibles los campos que podemos configurar.

¿Te ha resultado útil esta información? 🍺

Si este post te ha resuelto un problema, invítame a un café o a una cerveza. Con este pequeño gesto me animas a seguir escribiendo.

Comentarios

Deja un comentario

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

  • El fin del tratamiento es únicamente la moderación de comentarios para evitar spam
  • La legitimación es tu consentimiento al comentar
  • No se comunicará ningún dato a terceros salvo por obligación legal
  • Tienes derecho al acceso, rectificación y eliminación de los comentarios