{"id":233809,"date":"2023-02-23T17:52:00","date_gmt":"2023-02-23T14:52:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233809"},"modified":"2023-02-23T17:55:42","modified_gmt":"2023-02-23T14:55:42","slug":"tutorial-crear-un-control-deslizante-como-un-bloque-dinamico-de-gutenberg","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/tutorial-crear-un-control-deslizante-como-un-bloque-dinamico-de-gutenberg\/","title":{"rendered":"Tutorial: crear un control deslizante como un bloque din\u00e1mico de Gutenberg"},"content":{"rendered":"\n<p>Este tutorial explicar\u00e1 c\u00f3mo crear un bloque din\u00e1mico de WordPress Gutenberg. El resultado final es un control deslizante que muestra la imagen destacada de las publicaciones de categor\u00edas seleccionadas. El c\u00f3digo incluye el uso de un componente de orden superior (<code>withSelect<\/code>) para obtener todas las categor\u00edas dentro del editor de bloques.<\/p>\n<h2>que haremos<\/h2>\n<p>El bloque representar\u00e1 un control deslizante simple utilizando el script <a href=\"http:\/\/jquery.malsup.com\/cycle2\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">jQuery Cycle2<\/a>. Pero puede usar cualquier otro script de control deslizante. El bloque dentro del editor mostrar\u00e1 una lista de todas las categor\u00edas, lo que permitir\u00e1 al usuario seleccionar una categor\u00eda. Al mostrar el bloque en la interfaz, obtendr\u00e1 de forma din\u00e1mica las publicaciones de la categor\u00eda elegida y mostrar\u00e1 sus im\u00e1genes destacadas como diapositivas. Este tutorial lo mantendr\u00e1 bastante simple, permiti\u00e9ndole expandir y ajustar su control deslizante como lo desee.<\/p>\n<p>He optado por no mostrar la presentaci\u00f3n de diapositivas dentro del editor. Por lo general, se asegurar\u00eda de que el renderizado en el editor y la interfaz sean iguales. Pero en el caso de un control deslizante, me gusta mantenerlo simple para no molestar al usuario con animaciones constantes dentro del editor.<\/p>\n<p>El bloque tendr\u00e1 solo dos configuraciones; la elecci\u00f3n de la categor\u00eda y el n\u00famero de diapositivas (mensajes). Recomiendo agregar m\u00e1s configuraciones, como velocidad de deslizamiento, configuraciones para mostrar p\u00edldoras, flechas, texto y otras configuraciones t\u00edpicas del control deslizante. Deber\u00eda ser bastante simple agregar estas configuraciones usted mismo.<\/p>\n<p>Todo el c\u00f3digo est\u00e1 escrito en Javascript ES6 \/ ES2015+. Tenga en cuenta que este c\u00f3digo necesita que Babel transforme y cree los archivos Javascript finales. Consulte la gu\u00eda a continuaci\u00f3n si no sabe c\u00f3mo hacerlo.<\/p>\n<h2>configurar los archivos<\/h2>\n<p>En este ejemplo estamos creando el bloque dentro de un tema. En la carpeta del tema tengo una subcarpeta &#8216; <code>gutenberg\/<\/code>&#8216; donde he colocado mi <code>package.json<\/code>y <code>webpack-config.js<\/code>. Dentro de la subcarpeta &#8216; <code>src\/<\/code>&#8216; en esta carpeta es donde coloco todos mis archivos de compilaci\u00f3n. La configuraci\u00f3n de mi paquete web est\u00e1 configurada para colocar los archivos de compilaci\u00f3n en la subcarpeta de mi tema &#8216; <code>assets\/js\/<\/code>&#8216;.<\/p>\n<p>Cree un nuevo archivo fuente vac\u00edo <code>theme-folder\/gutenberg\/src\/block-slider.js<\/code>y configure Webpack para crear el archivo de compilaci\u00f3n en <code>theme-folder\/assets\/js\/block-slider.js<\/code>. Puede cambiar las ubicaciones y\/o los nombres de archivo como desee, solo recuerde ajustar el c\u00f3digo a continuaci\u00f3n.<\/p>\n<p>Tambi\u00e9n necesitamos descargar el script deslizante necesario. Puede <a href=\"http:\/\/jquery.malsup.com\/cycle2\/download\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">descargar Cycle2 en este enlace<\/a>, o puede usar cualquier otra secuencia de comandos de diapositivas y ajustar el c\u00f3digo a continuaci\u00f3n. Estoy colocando el <code>jquery.cycle2.min.js<\/code>archivo en mi carpeta de <code>\/assets\/js\/<\/code>carpetas de temas.<\/p>\n<p>Tambi\u00e9n preparar\u00e9 un peque\u00f1o archivo CSS que se cargar\u00e1 solo en el editor. Solo hacemos una peque\u00f1a pieza de estilo para que la selecci\u00f3n de categor\u00eda sea \u00f3ptima. Creo un archivo vac\u00edo <code>editor-block-slider.css<\/code>y lo coloco en <code>theme-folder\/assets\/css\/<\/code>.<\/p>\n<p>Finalmente vamos a un archivo PHP que est\u00e1 cargado en el tema. En aras de la simplicidad, estoy haciendo la parte de PHP en el archivo <code>functions.php<\/code>.<\/p>\n<h2>Registrar el bloque de Gutenberg en PHP<\/h2>\n<p>Todos los bloques de Gutenberg deben estar registrados con <code>[register_block_type](https:\/\/developer.wordpress.org\/reference\/functions\/register_block_type\/)()<\/code>. Prefiero llamarlo dentro de una funci\u00f3n enganchada a <code>init<\/code>. El primer par\u00e1metro es el nombre de su bloque, incluido el espacio de nombres. He decidido llamar a mi secuencia de comandos deslizante <code>awp\/slider<\/code>(ajustar como quieras). El segundo argumento es una matriz de argumentos.<\/p>\n<p>Dentro de la misma funci\u00f3n, registrar\u00e9 el script de compilaci\u00f3n <code>[wp_register_script](https:\/\/developer.wordpress.org\/reference\/functions\/wp_register_script\/)()<\/code>y registrar\u00e9 mi archivo CSS del editor con <code>[wp_register_style](https:\/\/developer.wordpress.org\/reference\/functions\/wp_register_style\/)()<\/code>. Ambos identificadores se agregar\u00e1n como argumentos a &#8216; <code>editor_script<\/code>&#8216; y &#8216; <code>editor_style<\/code>&#8216;, respectivamente. En cuanto a las dependencias, agregu\u00e9 algunos de los paquetes m\u00e1s b\u00e1sicos para el script para garantizar que nuestro script de bloque se cargue en el orden correcto. En cuanto al estilo del editor, usar &#8216; <code>wp-edit-blocks<\/code>&#8216; es una buena dependencia para evitar que se anulen sus estilos.<\/p>\n<p>Y finalmente, debido a que este es un bloque din\u00e1mico, tambi\u00e9n debemos agregar el <code>render_callback<\/code>argumento &#8216; &#8216;, que apunta a una funci\u00f3n que es responsable de representar el bloque en la interfaz.<\/p>\n<pre><code>add_action('init', function() {\n    wp_register_script(\n        'awp-block-slider-js', \n        get_template_directory_uri(). '\/assets\/js\/block-slider.js', \n        ['wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-data']\n    );\n    wp_register_style(\n        'awp-block-slider-style', \n        get_template_directory_uri(). '\/assets\/css\/editor-block-slider.css', \n        ['wp-edit-blocks']\n    );\n\u00a0\n    register_block_type('awp\/slider', [\n        'editor_script' =&gt; 'awp-block-slider-js',\n        'editor_style' =&gt; 'awp-block-slider-style',\n        'render_callback' =&gt; 'awp_gutenberg_slider_render',\n    ]);\n});<\/code><\/pre>\n<p>Finalmente definimos la funci\u00f3n render. Obtenemos dos par\u00e1metros para la devoluci\u00f3n de llamada de la funci\u00f3n; una matriz de atributos del bloque y el contenido interno (no utilizado en este bloque). Simplemente devolver\u00e9 una cadena ficticia. Volveremos y desarrollaremos la funci\u00f3n de renderizado m\u00e1s tarde. Recuerde devolver una cadena, no un eco.<\/p>\n<pre><code>function awp_gutenberg_slider_render($attributes, $content) {\n    return 'Slider render comes here.';\n}<\/code><\/pre>\n<p>Volveremos a la funci\u00f3n de representaci\u00f3n de PHP al final de este tutorial. \u00a1Ahora es el momento de pasar a Javascript!<\/p>\n<h2>Registre un bloque de Gutenberg personalizado en Javascript<\/h2>\n<p>Abramos nuestro <code>block-slider.js<\/code>archivo fuente. En este punto, iniciar\u00e9 el script (<code>npm run start<\/code>) para transformar todo lo que hacemos en este archivo en el archivo de compilaci\u00f3n a medida que avanzamos. Necesitamos registrar el bloque usando <code>[registerBlockType](https:\/\/developer.wordpress.org\/block-editor\/developers\/block-api\/block-registration\/)()<\/code>. Echa un vistazo al enlace para ver todos los argumentos posibles.<\/p>\n<p>Como decidimos <code>register_block_type()<\/code>en PHP, nuestro bloque se llama <code>awp\/slider<\/code>. Tambi\u00e9n queremos agregar dos atributos al bloque, como se mencion\u00f3 anteriormente: uno para el ID del t\u00e9rmino seleccionado y otro para el n\u00famero de diapositivas.<\/p>\n<p>Tambi\u00e9n me gusta agregar la funcionalidad de alineaci\u00f3n de bloques. Se agregar\u00e1 autom\u00e1ticamente agregando &#8216; <code>align<\/code>&#8216; al <code>supports<\/code>objeto. Si desea todas las alineaciones de bloques, simplemente puede configurarlas <code>align<\/code>como verdaderas. Sin embargo, un control deslizante alineado a la izquierda o a la derecha no tiene mucho sentido, por lo que definir\u00e9 los tipos espec\u00edficos de alineaci\u00f3n de bloques que admite este bloque: &quot;Alinear al centro&quot; (&#8216; <code>center<\/code>&#8216;), &quot;Ancho ancho&quot; (&#8216; <code>wide<\/code>&#8216;) y &quot; Ancho completo&quot; (&#8216; <code>full<\/code>&#8216;). Adem\u00e1s, para definir una alineaci\u00f3n predeterminada y hacerla accesible desde PHP, agrego &#8216; <code>align<\/code>&#8216; como atributo a nuestro bloque.<\/p>\n<p>Establec\u00ed el argumento del bloque <code>edit<\/code>en un componente separado que crearemos a continuaci\u00f3n. Y finalmente la <code>save<\/code>funci\u00f3n simplemente devuelve <code>null<\/code>, porque este es un bloque din\u00e1mico.<\/p>\n<pre><code>const { __ } = wp.i18n;\nconst { registerBlockType } = wp.blocks;\n\u00a0\nregisterBlockType('awp\/slider', {\n    title: __('AWP Slider', 'awp'),\n    icon: 'slides',\n    category: 'common',\n    supports: {\n        align: ['center', 'wide', 'full']\n    },\n    attributes: {\n        align: {\n            type: 'string',\n            default: 'center'\n        },\n        termId: {\n            type: 'number',\n            default: 0\n        },\n        numSlides: {\n            type: 'number',\n            default: 3\n        },\n    },\n    edit: BlockEdit,\n    save:() =&gt; { return null; }\n});<\/code><\/pre>\n<p>Necesitamos definir el componente para la <code>edit<\/code>propiedad. Antes del c\u00f3digo de registro, defino un componente de funci\u00f3n <code>BlockEdit<\/code>que simplemente representa un <code>div<\/code>y un <code>Placeholder<\/code>texto ficticio.<\/p>\n<pre><code>const { __ } = wp.i18n;\nconst { registerBlockType } = wp.blocks;\nconst { Placeholder } = wp.components;\nconst BlockEdit = (props) =&gt; {\n    return(\n        &lt;div className={props.className}&gt;\n            &lt;Placeholder\n                label={__('Slider Category', 'awp')}\n            &gt;\n                Select category comes here.\n            &lt;\/Placeholder&gt;\n        &lt;\/div&gt;\n    );\n}\n\u00a0\nregisterBlockType('awp\/slider', {\n    ...<\/code><\/pre>\n<p><code>[Placeholder](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/placeholder)<\/code>es un buen componente para renderizar un \u00e1rea para la configuraci\u00f3n, y no necesariamente para el renderizado real de un bloque. Dentro del <code>Placeholder<\/code>componente es donde representamos una lista de t\u00e9rminos para elegir.<\/p>\n<p>\u00a1En este punto, nuestro bloque deber\u00eda estar disponible en WordPress Gutenberg! Creemos una nueva publicaci\u00f3n, agreguemos un nuevo bloque y busquemos nuestro bloque dentro de la categor\u00eda Com\u00fan. As\u00ed es como se ve nuestro bloque actualmente:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151906-61e4d14fb8d7b.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151906-61e4d14fb8d7b.png\" alt=\"Tutorial: crear un control deslizante como un bloque din\u00e1mico de Gutenberg\"><\/a><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151906-61e4d150ae184.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151906-61e4d150ae184.png\" alt=\"Tutorial: crear un control deslizante como un bloque din\u00e1mico de Gutenberg\"><\/a><\/p>\n<h2>Adici\u00f3n de la configuraci\u00f3n del Inspector<\/h2>\n<p>Agreguemos algunas configuraciones al Inspector (barra lateral derecha del editor). Como se mencion\u00f3, nuestro bloque solo tiene una configuraci\u00f3n; n\u00famero de diapositivas. Aqu\u00ed es donde te recomiendo que agregues m\u00e1s configuraciones para tu bloque deslizante. Recuerde registrar atributos para cada configuraci\u00f3n que agregue.<\/p>\n<p>Para agregar algo al Inspector usamos el componente <code>[InspectorControls](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/block-editor\/src\/components\/inspector-controls)<\/code>( ). <code>wp.blockEditor<\/code>Dentro representamos un <code>[PanelBody](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/panel#panelbody)<\/code>( <code>wp.components<\/code>) para agregar una nueva secci\u00f3n contra\u00edble. Luego, simplemente renderizamos un <code>[RangeControl](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/range-control)<\/code>( <code>wp.components<\/code>) para crear una configuraci\u00f3n de entrada para elegir el n\u00famero de diapositivas. Establecemos el m\u00ednimo en 1 y el m\u00e1ximo en 10. Conectamos el evento <code>value<\/code>y <code>onChange<\/code>al atributo <code>numSlides<\/code>.<\/p>\n<pre><code>const { __ } = wp.i18n;\nconst { registerBlockType } = wp.blocks;\nconst { InspectorControls } = wp.blockEditor;\nconst { Placeholder, PanelBody, RangeControl } = wp.components;\n\u00a0\nconst BlockEdit = (props) =&gt; {\n    const { attributes, setAttributes } = props;\n\u00a0\n    return(\n        &lt;div className={props.className}&gt;\n            &lt;InspectorControls&gt;\n                &lt;PanelBody\n                    title={__('Slider Settings', 'awp')}\n                    initialOpen={true}\n                &gt;\n                    &lt;RangeControl\n                        label={__('Number of slides', 'awp')}\n                        value={attributes.numSlides}\n                        onChange={(val) =&gt; setAttributes({ numSlides: val })}\n                        min={1}\n                        max={10}\n                    \/&gt;\n                &lt;\/PanelBody&gt;\n            &lt;\/InspectorControls&gt;\n            &lt;Placeholder\n                ...<\/code><\/pre>\n<p>Con el c\u00f3digo anterior, ahora deber\u00edamos obtener una buena secci\u00f3n con un control deslizante de rango para configurar el n\u00famero de diapositivas.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151906-61e4d15191aa1.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151906-61e4d15191aa1.png\" alt=\"Tutorial: crear un control deslizante como un bloque din\u00e1mico de Gutenberg\"><\/a><\/p>\n<p>Nuevamente, le recomiendo que juegue agregando m\u00e1s configuraciones a su control deslizante. El siguiente paso es crear el elemento para representar una lista de categor\u00edas para elegir.<\/p>\n<h2>Creaci\u00f3n de un componente de selecci\u00f3n de categor\u00eda<\/h2>\n<p>Para mantener nuestro c\u00f3digo ordenado y reutilizable, creemos el componente selector de categor\u00eda en un archivo separado. Dentro de la carpeta de compilaci\u00f3n, creo un nuevo archivo <code>awp-category-picker.js<\/code>.<\/p>\n<p>Dentro de este archivo, definimos un componente que recorrer\u00e1 todas las categor\u00edas actualmente en WordPress y las representar\u00e1 de alguna manera. Para obtener categor\u00edas, debemos envolverlo dentro de un llamado componente de orden superior, que proporcionar\u00e1 a nuestro componente lo que necesitamos a trav\u00e9s de accesorios. Para ello utilizaremos <code>[withSelect](https:\/\/developer.wordpress.org\/block-editor\/packages\/packages-data\/#withSelect)<\/code>. Dentro <code>withSelect<\/code>podemos hacer una solicitud para buscar todas las categor\u00edas en WordPress usando el selector de tienda <code>[select](https:\/\/developer.wordpress.org\/block-editor\/packages\/packages-data\/#select)()<\/code>. Nosotros podemos usar:<\/p>\n<pre><code>select('core').getEntityRecords('taxonomy', '&lt;category_slug&gt;', &lt;args&gt;)<\/code><\/pre>\n<p>para obtener todos los t\u00e9rminos dentro del slug de taxonom\u00eda proporcionado. Si no est\u00e1 familiarizado con los componentes y selectores de orden superior en WordPress Gutenberg, tengo una publicaci\u00f3n que explica este concepto con m\u00e1s detalle: <a href=\"https:\/\/wordpress.mediadoma.com\/es\/crear-bloque-de-gutenberg-personalizado-parte-10-obtener-publicaciones-y-componentes-de-orden-superior\/\" title=\"Crear un bloque de Gutenberg personalizado - Parte 10: Obtenci\u00f3n de publicaciones y componentes de orden superior\">Crear un bloque de Gutenberg personalizado &#8211; Parte 10: Obtenci\u00f3n de publicaciones y componentes de orden superior<\/a>.<\/p>\n<p>Debido a que necesitamos exportar un componente de este archivo, colocamos la combinaci\u00f3n de <code>withSelect<\/code>y nuestro componente definido en la <code>export default<\/code>instrucci\u00f3n. Nuestro <code>CategorySelect<\/code>componente simplemente devuelve un div con un texto ficticio para que podamos ver que funciona. El <code>withSelect<\/code>debe proporcionar el apoyo &#8216; <code>terms<\/code>&#8216; a <code>CategorySelect<\/code>. He agregado una <code>console.log()<\/code>en este accesorio para que podamos ver que funciona.<\/p>\n<pre><code>const { withSelect } = wp.data;\n\u00a0\nconst CategorySelect = (props) =&gt; {\n    console.log(props.terms);\n\u00a0\n    return(\n        &lt;div&gt;This is category select&lt;\/div&gt;\n    );\n}\n\u00a0\nexport default withSelect((select, props) =&gt; {\n    return {\n        terms: select('core').getEntityRecords('taxonomy', 'category', {per_page: -1})\n    }\n})(CategorySelect);<\/code><\/pre>\n<p>Lo \u00faltimo que tenemos que hacer es importar y usar este componente selector de categor\u00eda en nuestro bloque personalizado.<\/p>\n<p>De vuelta <code>block-slider.js<\/code>, primero debemos importar el componente en la parte superior del archivo. Y dentro de nuestro <code>Placeholder<\/code>componente simplemente renderizamos el componente.<\/p>\n<pre><code>const { Placeholder, PanelBody, RangeControl } = wp.components;\n\u00a0\nimport CategorySelect from '.\/awp-category-picker';\n\u00a0\nconst BlockEdit = (props) =&gt; {\n        ...\n            &lt;Placeholder\n                label={__('Slider Category', 'awp')}\n            &gt;\n                &lt;CategorySelect \n                \/&gt;\n            &lt;\/Placeholder&gt;\n        ...<\/code><\/pre>\n<p>Con el c\u00f3digo anterior, su bloque ahora deber\u00eda representar el div del <code>CategorySelect<\/code>componente. Si abre la consola en su navegador, tambi\u00e9n deber\u00eda ver algunos registros. Recuerde que <code>withSelect<\/code>es una consulta as\u00edncrona, lo que significa que podr\u00eda procesarse varias veces. La(s) primera(s) vez(es) que los t\u00e9rminos prop son <code>null<\/code>. Pero los \u00faltimos registros deber\u00edan terminar con una serie de t\u00e9rminos de categor\u00eda.<\/p>\n<p>\u00a1Excelente! \u00a1Sigamos trabajando con nuestro <code>CategorySelect<\/code>componente y hagamos que realmente represente la lista de t\u00e9rminos que le permite al usuario seleccionar uno!<\/p>\n<h3>Representaci\u00f3n de una lista de t\u00e9rminos para elegir<\/h3>\n<p>Hay muchas formas de representar una lista de opciones donde el usuario puede seleccionar un elemento. Si desea algo realmente simple, puede representar un men\u00fa desplegable de selecci\u00f3n est\u00e1ndar (<code>[SelectControl](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/select-control)<\/code>). Depende completamente de ti. He optado por un enfoque m\u00e1s limpio y agradable usando <code>[MenuGroup](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/menu-group)<\/code>( <code>wp.components<\/code>) y <code>[MenuItem](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/menu-item)<\/code>( <code>wp.components<\/code>).<\/p>\n<p>Dentro de un <code>MenuGroup<\/code>componente, debemos recorrer la <code>props.terms<\/code>matriz y, para cada elemento, queremos mostrar un <code>MenuItem<\/code>componente que represente el nombre del t\u00e9rmino. Y, por supuesto, solo queremos renderizar esto si <code>props.terms<\/code>realmente contiene algo (solicitud as\u00edncrona, \u00bfrecuerdas?).<\/p>\n<pre><code>const { withSelect } = wp.data;\nconst { MenuGroup, MenuItem } = wp.components;\n\u00a0\nconst CategorySelect = (props) =&gt; {\n    const { terms } = props;\n    return(\n        &lt;MenuGroup\n            className=\"awp-categoryselect\"\n        &gt;\n            {terms &amp;&amp; (terms.map((item) =&gt; (&lt;MenuItem\n                        role=\"menuitemradio\"\n                    &gt;\n                        {item.name}\n                    &lt;\/MenuItem&gt;\n                ))\n            )}\n        &lt;\/MenuGroup&gt;\n    );\n}\n\u00a0\nexport default withSelect((select, props) =&gt; {\n    ...<\/code><\/pre>\n<p>Le he dado al <code>MenuGroup<\/code>componente una clase personalizada, ya que necesitaremos apuntar a esto con CSS. Y configur\u00e9 el accesorio <code>role<\/code>en <code>MenuItem<\/code>&#8216; <code>menuitemradio<\/code>&#8216; para asegurarme de que solo se pueda elegir uno a la vez. Por defecto, funcionan como casillas de verificaci\u00f3n, lo que permite elegir varios elementos.<\/p>\n<p>Con el c\u00f3digo anterior, nuestro bloque deber\u00eda ahora (despu\u00e9s de un peque\u00f1o segundo) mostrar una buena lista de todas las categor\u00edas en su instancia de WordPress.<\/p>\n<p>Puede notar que nuestro bloque se expandir\u00e1 para contener todas las categor\u00edas. Si estamos en una instancia de WordPress con muchas categor\u00edas, esto r\u00e1pidamente se convierte en un problema. Queremos asegurarnos de que el selector sea un contenedor de altura m\u00e1xima que obtenga una barra de desplazamiento vertical si hay muchas categor\u00edas. Aqu\u00ed es donde entra nuestro archivo CSS.<\/p>\n<p>En nuestro <code>editor-block-slider.css<\/code>archivo agregar:<\/p>\n<pre><code>.awp-categoryselect div {\n    max-height: 200px;\n    overflow: hidden scroll;\n    border: 1px solid #b3bcc0;\n}<\/code><\/pre>\n<p>Este CSS apunta al interior de <code>div<\/code>nuestro interior <code>MenuGroup<\/code>y se asegura de que nunca supere los 200 px. Si el contenido de la <code>MenuGroup<\/code>se hace m\u00e1s grande (m\u00e1s categor\u00edas) se mostrar\u00e1 una barra de desplazamiento vertical. Este es el m\u00ednimo de CSS para nuestro bloque, pero, por supuesto, puede agregar m\u00e1s CSS si lo desea.<\/p>\n<p>Lo \u00faltimo que debemos corregir en nuestro selector de categor\u00edas es la funcionalidad para mostrar el elemento seleccionado actualmente y permitir que el usuario seleccione un t\u00e9rmino de la lista. Para ello necesitamos pasar algunos accesorios a este componente desde nuestro bloque.<\/p>\n<p>Necesitamos <code>block-slider.js<\/code>pasar el t\u00e9rmino seleccionado actual (valor del atributo <code>termId<\/code>) y una funci\u00f3n para actualizar el t\u00e9rmino seleccionado (<code>setAttributes<\/code>) como apoyos a nuestro componente selector de categor\u00eda.<\/p>\n<pre><code>...\n\u00a0\nconst BlockEdit = (props) =&gt; {\n    const { attributes, setAttributes } = props;\n\u00a0\n    const selectTerm = (termId) =&gt; {\n        setAttributes({ termId: termId });\n    }\n\u00a0\n    return(\n        ...\n            &lt;Placeholder\n                label={__('Slider Category', 'awp')}\n            &gt;\n                &lt;CategorySelect \n                    selectedTermId={attributes.termId}\n                    selectTerm={selectTerm}\n                \/&gt;\n            &lt;\/Placeholder&gt;\n        ...<\/code><\/pre>\n<p>En el c\u00f3digo anterior en la l\u00ednea <code>#6<\/code>, definimos una funci\u00f3n que simplemente actualiza el atributo <code>termId<\/code>. Pasamos este nombre de funci\u00f3n como prop a <code>CategorySelect<\/code>at line <code>#17<\/code>. Y en la l\u00ednea <code>#16<\/code>pasamos el valor actual de <code>termId<\/code>. Con podemos actualizar nuestro <code>CategorySelect<\/code>componente para reflejar el elemento elegido y permitir que el usuario elija un t\u00e9rmino.<\/p>\n<p>De vuelta <code>awp-category-picker.js<\/code>, agregamos algunos accesorios nuevos en <code>MenuItem<\/code>. Devolvemos <code>true<\/code>o <code>false<\/code>para la propiedad <code>isSelected<\/code>si el ID del t\u00e9rmino actual es o no el mismo que el seleccionado actualmente. Iniciamos la <code>selectTerm<\/code>funci\u00f3n en el <code>onClick<\/code>evento, pasando el t\u00e9rmino ID. Y para que el elemento seleccionado sea visual, agregamos condicionalmente un \u00edcono antes de cada elemento.<\/p>\n<pre><code>...\nconst CategorySelect = (props) =&gt; {\n    const { terms, selectedTermId, selectTerm } = props;\n\u00a0\n    return(\n        &lt;MenuGroup\n            className=\"awp-categoryselect\"\n        &gt;\n            {terms &amp;&amp; (terms.map((item) =&gt; (&lt;MenuItem\n                        role=\"menuitemradio\"\n                        isSelected={item.id == selectedTermId}\n                        icon={item.id == selectedTermId? 'yes': 'no-alt'}\n                        onClick={() =&gt; selectTerm(item.id)}\n                    &gt;\n                        {item.name}\n                    &lt;\/MenuItem&gt;\n                ))\n            )}\n        ...<\/code><\/pre>\n<p>Con esto, nuestro selector de categor\u00eda deber\u00eda verse as\u00ed:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151906-61e4d1525afb7.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151906-61e4d1525afb7.png\" alt=\"Tutorial: crear un control deslizante como un bloque din\u00e1mico de Gutenberg\"><\/a><\/p>\n<p>La lista debe marcar claramente el t\u00e9rmino seleccionado con un \u00edcono de verificaci\u00f3n, y puede hacer clic en cualquier t\u00e9rmino para seleccionar ese t\u00e9rmino en su lugar.<\/p>\n<p>\u00a1Eso fue todo para el editor y la parte de Javascript! Lo que queda ahora es el renderizado frontend, que haremos en PHP.<\/p>\n<h2>Renderizar el bloque din\u00e1mico en PHP<\/h2>\n<p>Antes de sumergirnos en la funci\u00f3n de renderizado, primero ocup\u00e9monos de algunas cosas.<\/p>\n<p>Primero, debemos poner en cola el script de ciclo2 en la interfaz para que nuestro c\u00f3digo del control deslizante se convierta en un control deslizante. Hacemos esto con una funci\u00f3n simple conectada a <code>wp_enqueue_scripts<\/code>. Ajuste lo siguiente si opt\u00f3 por otra secuencia de comandos deslizante.<\/p>\n<pre><code>add_action('wp_enqueue_scripts', function() {\n    wp_enqueue_script(\n        'cycle2-slider-js', \n        get_template_directory_uri(). '\/assets\/js\/jquery.cycle2.min.js', \n        ['jquery'], \n        '', \n        true\n    );\n});<\/code><\/pre>\n<p>En segundo lugar, queremos volver a la <code>register_block_type()<\/code>llamada a la funci\u00f3n. Cuando manejamos bloques din\u00e1micos definitivamente deber\u00edamos agregar un nuevo argumento; <code>attributes<\/code>. En este argumento, definimos todos los atributos que hemos definido <code>registerBlockType<\/code>en Javascript, incluidos sus valores predeterminados. Si no lo hacemos, no todos los atributos estar\u00e1n disponibles en nuestra devoluci\u00f3n de llamada de renderizado. Si un atributo se dej\u00f3 sin cambios en el editor de bloques, el atributo y su valor no estar\u00e1n disponibles en la matriz de atributos en PHP. Por lo tanto, le recomiendo que siempre tenga cuidado de agregar la <code>attributes<\/code>matriz a la <code>register_block_type()<\/code>funci\u00f3n de PHP cuando trabaje con bloques din\u00e1micos. Para nuestro bloque se ver\u00eda as\u00ed:<\/p>\n<pre><code>register_block_type('awp\/slider', [\n    'editor_script' =&gt; 'awp-block-slider-js',\n    'editor_style' =&gt; 'awp-block-slider-style',\n    'render_callback' =&gt; 'awp_gutenberg_slider_render',\n    'attributes' =&gt; [\n        'align' =&gt; ['type' =&gt; 'string', 'default' =&gt; 'center'],\n        'termId' =&gt; ['type' =&gt; 'number', 'default' =&gt; 0],\n        'numSlides' =&gt; ['type' =&gt; 'number', 'default' =&gt; 3]\n    ]\n]);<\/code><\/pre>\n<p>Ahora volvemos a nuestra funci\u00f3n de renderizado de devoluci\u00f3n de llamada <code>awp_gutenberg_slider_render()<\/code>. La salida depende completamente de usted, especialmente si ha elegido usar otro script de control deslizante. El siguiente es un ejemplo simple.<\/p>\n<p>La idea principal es que comprobemos si se eligi\u00f3 o no un t\u00e9rmino (<code>$attributes['termId']<\/code>). Si se completa, creamos un <code>[WP_Query](https:\/\/developer.wordpress.org\/reference\/classes\/wp_query\/)()<\/code>con argumentos para el n\u00famero de publicaciones (<code>$attributes['numSlides']<\/code>) y la ID de categor\u00eda seleccionada. Luego, se trata de generar el HTML adecuado para que Cycle2 funcione, recorrer las publicaciones y mostrar sus im\u00e1genes destacadas como diapositivas.<\/p>\n<pre><code>function awp_gutenberg_slider_render($attributes, $content) {\n    if (empty($attributes['termId'])) {\n        return '';\n    }\n\u00a0\n    $postQuery = new WP_Query([\n        'posts_per_page' =&gt; $attributes['numSlides'],\n        'cat' =&gt; $attributes['termId']\n    ]);\n\u00a0\n    if ($postQuery-&gt;have_posts()) {\n        $output = '&lt;div class=\"wp-block-awp-slider align'. $attributes['align']. '\"&gt;';\n        $output .= '&lt;div class=\"cycle-slideshow\" data-cycle-timeout=4000&gt;';\n        while ($postQuery-&gt;have_posts()) {\n            $postQuery-&gt;the_post();\n\u00a0\n            if (has_post_thumbnail()) {\n                $img_url = get_the_post_thumbnail_url(get_the_ID(), 'loop-thumbnail');\n                $output .= '&lt;img src=\"'. $img_url. '\" \/&gt;';\n            }\n        }\n        wp_reset_postdata();\n        $output .= '&lt;\/div&gt;';\n        $output .= '&lt;\/div&gt;';\n\u00a0\n        return $output;\n\u00a0\n    } else {\n        return '';\n    }\n}<\/code><\/pre>\n<p>Tenga en cuenta c\u00f3mo agrego la clase de alineaci\u00f3n de bloque adecuada en l\u00ednea <code>#12<\/code>. El resultado deber\u00eda ser un control deslizante de las im\u00e1genes destacadas. Tenga en cuenta que este es un ejemplo b\u00e1sico que tiene algunos defectos. Por ejemplo, buscamos las \u00faltimas tres publicaciones de la categor\u00eda seleccionada. Pero suponiendo que uno de ellos no tenga una imagen destacada, el control deslizante solo mostrar\u00e1 dos publicaciones.<\/p>\n<p>Lo importante a recordar es devolver una cadena y no repetirla. Tambi\u00e9n recomiendo usar alg\u00fan tipo de funcionalidad de plantillas en su tema para renderizados de bloques din\u00e1micos como estos. R\u00e1pidamente puede volverse complicado arreglar y construir HTML como una cadena.<\/p>\n<h2>Ultimas palabras<\/h2>\n<p>Este tutorial le ha mostrado c\u00f3mo crear un bloque din\u00e1mico personalizado de Gutenberg de WordPress donde renderiza su contenido de interfaz en PHP. Y ha visto c\u00f3mo usar el componente de orden superior <code>withSelect<\/code>para consultar todos los t\u00e9rminos de categor\u00eda y un m\u00e9todo para mostrar una lista seleccionable.<\/p>\n<p>Todo el c\u00f3digo anterior est\u00e1 escrito de la manera m\u00e1s simple posible. Solo he agregado el m\u00ednimo absoluto de configuraciones. El control deslizante funciona, pero generalmente desea m\u00e1s, por ejemplo, hacer enlaces de diapositivas, mostrar t\u00edtulos de las publicaciones, flechas del control deslizante o la opci\u00f3n de personalizar la velocidad u otras configuraciones del control deslizante. La idea es mostrarle los conceptos b\u00e1sicos y facilitarle la ampliaci\u00f3n, la ampliaci\u00f3n y los cambios para adaptarse a las necesidades de su proyecto.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fuente de grabaci\u00f3n:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Un tutorial sobre c\u00f3mo crear un bloque din\u00e1mico de WordPress Gutenberg con withSelect y PHP render. El resultado final es un control deslizante.<\/p>\n","protected":false},"author":1,"featured_media":151907,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[892,892,810,716,716,935,935,1110,810,840,840,861,861],"tags":[1172],"class_list":["post-233809","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo","category-complementos","category-desarrollador","category-gutenberg-2","category-n-a","category-tutoriales","category-wordpress-2","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/233809","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/comments?post=233809"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/233809\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/151907"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=233809"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=233809"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=233809"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}