{"id":233878,"date":"2023-02-23T17:53:00","date_gmt":"2023-02-23T14:53:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233878"},"modified":"2023-02-23T17:55:41","modified_gmt":"2023-02-23T14:55:41","slug":"tutorial-criar-um-slider-como-um-bloco-gutenberg-dinamico","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/tutorial-criar-um-slider-como-um-bloco-gutenberg-dinamico\/","title":{"rendered":"Tutorial: Criar um Slider como um Bloco Gutenberg Din\u00e2mico"},"content":{"rendered":"\n<p>Este tutorial mostrar\u00e1 como criar um bloco din\u00e2mico do WordPress Gutenberg. O resultado final \u00e9 um controle deslizante que mostra a imagem em destaque das postagens da categoria selecionada. O c\u00f3digo inclui o uso de um componente de ordem superior (<code>withSelect<\/code>) para buscar todas as categorias no editor de blocos.<\/p>\n<h2>O que vamos fazer<\/h2>\n<p>O bloco renderizar\u00e1 um slider simples usando o script <a href=\"http:\/\/jquery.malsup.com\/cycle2\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">jQuery Cycle2<\/a>. Mas voc\u00ea pode usar qualquer outro script de controle deslizante. O bloco ir\u00e1 dentro do editor renderizar uma lista de todas as categorias permitindo ao usu\u00e1rio selecionar uma categoria. Ao exibir o bloco no frontend, ele buscar\u00e1 dinamicamente as postagens da categoria escolhida e mostrar\u00e1 suas imagens em destaque como slides. Este tutorial ir\u00e1 mant\u00ea-lo bastante simples, permitindo que voc\u00ea expanda e ajuste seu controle deslizante como quiser.<\/p>\n<p>Optei por n\u00e3o renderizar a apresenta\u00e7\u00e3o de slides dentro do editor. Normalmente, voc\u00ea garante que a renderiza\u00e7\u00e3o no editor e no frontend seja a mesma. Mas no caso de um slider eu gosto de simplificar para n\u00e3o explodir o usu\u00e1rio com anima\u00e7\u00f5es constantes dentro do editor.<\/p>\n<p>O bloco ter\u00e1 apenas duas configura\u00e7\u00f5es; a escolha da categoria e o n\u00famero de slides (posts). Eu recomendo adicionar mais configura\u00e7\u00f5es, como velocidade do slide, configura\u00e7\u00f5es para exibir p\u00edlulas, setas, texto e outras configura\u00e7\u00f5es t\u00edpicas do controle deslizante. Deve ser bem simples adicionar essas configura\u00e7\u00f5es voc\u00ea mesmo.<\/p>\n<p>Todo o c\u00f3digo \u00e9 escrito em Javascript ES6 \/ ES2015+. Tenha em mente que este c\u00f3digo precisa do Babel para transformar e construir os arquivos Javascript finais. Confira o guia abaixo se voc\u00ea n\u00e3o sabe como.<\/p>\n<h2>Configure os arquivos<\/h2>\n<p>Neste exemplo estamos criando o bloco dentro de um tema. Na pasta do tema tenho uma subpasta &#8216; <code>gutenberg\/<\/code>&#8216; onde coloquei meu arquivo <code>package.json<\/code>e <code>webpack-config.js<\/code>. Dentro da subpasta &#8216; <code>src\/<\/code>&#8216; nesta pasta \u00e9 onde coloco todos os meus arquivos de compila\u00e7\u00e3o. Minha configura\u00e7\u00e3o do webpack est\u00e1 configurada para colocar os arquivos de compila\u00e7\u00e3o na subpasta do meu tema &#8216; <code>assets\/js\/<\/code>&#8216;.<\/p>\n<p>Crie um novo arquivo de origem vazio <code>theme-folder\/gutenberg\/src\/block-slider.js<\/code>e configure o Webpack para criar o arquivo de compila\u00e7\u00e3o em <code>theme-folder\/assets\/js\/block-slider.js<\/code>. Voc\u00ea pode alterar os locais e\/ou nomes de arquivos como quiser, apenas lembre-se de ajustar o c\u00f3digo abaixo.<\/p>\n<p>Tamb\u00e9m precisamos baixar o script de controle deslizante necess\u00e1rio. Voc\u00ea pode <a href=\"http:\/\/jquery.malsup.com\/cycle2\/download\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">baixar o Cycle2 neste link<\/a> ou pode usar qualquer outro script de slide e ajustar o c\u00f3digo abaixo. Estou colocando o <code>jquery.cycle2.min.js<\/code>arquivo na pasta da pasta do meu tema <code>\/assets\/js\/<\/code>.<\/p>\n<p>Tamb\u00e9m vou preparar um pequeno arquivo CSS que ser\u00e1 carregado apenas no editor. N\u00f3s apenas um pequeno peda\u00e7o de estilo para tornar a categoria ideal. Eu crio um arquivo vazio <code>editor-block-slider.css<\/code>e coloco em <code>theme-folder\/assets\/css\/<\/code>.<\/p>\n<p>Finalmente vamos para um arquivo PHP que \u00e9 carregado no tema. Para simplificar, estou fazendo a parte do PHP no arquivo <code>functions.php<\/code>.<\/p>\n<h2>Registre o bloco Gutenberg em PHP<\/h2>\n<p>Todos os blocos Gutenberg devem ser registrados com <code>[register_block_type](https:\/\/developer.wordpress.org\/reference\/functions\/register_block_type\/)()<\/code>. Eu prefiro cham\u00e1-lo dentro de uma fun\u00e7\u00e3o ligada a <code>init<\/code>. O primeiro par\u00e2metro \u00e9 o nome do seu bloco, incluindo o namespace. Eu decidi chamar meu script de controle deslizante <code>awp\/slider<\/code>(ajuste como quiser). O segundo argumento \u00e9 uma matriz de argumentos.<\/p>\n<p>Dentro da mesma fun\u00e7\u00e3o, registrarei o script de constru\u00e7\u00e3o <code>[wp_register_script](https:\/\/developer.wordpress.org\/reference\/functions\/wp_register_script\/)()<\/code>e registrarei meu arquivo CSS do editor com <code>[wp_register_style](https:\/\/developer.wordpress.org\/reference\/functions\/wp_register_style\/)()<\/code>. Ambos os identificadores ser\u00e3o adicionados como argumentos para &#8216; <code>editor_script<\/code>&#8216; e &#8216; <code>editor_style<\/code>&#8216;, respectivamente. Quanto \u00e0s depend\u00eancias, adicionei alguns dos pacotes mais b\u00e1sicos para o script para garantir que nosso script de bloco seja carregado na ordem correta. Quanto ao estilo do editor, usar &#8216; <code>wp-edit-blocks<\/code>&#8216; \u00e9 uma boa depend\u00eancia para evitar que seus estilos sejam substitu\u00eddos.<\/p>\n<p>E por fim por se tratar de um bloco din\u00e2mico, precisamos tamb\u00e9m adicionar o <code>render_callback<\/code>argumento &#8216; &#8216;, apontando para uma fun\u00e7\u00e3o que \u00e9 respons\u00e1vel por renderizar o bloco no frontend.<\/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>Por fim, definimos a fun\u00e7\u00e3o de renderiza\u00e7\u00e3o. Obtemos dois par\u00e2metros para o retorno de chamada da fun\u00e7\u00e3o; uma matriz de atributos do bloco e o conte\u00fado interno (n\u00e3o usado neste bloco). Eu simplesmente retornarei alguma string fict\u00edcia. Voltaremos e detalharemos a fun\u00e7\u00e3o de renderiza\u00e7\u00e3o mais tarde. Lembre-se de retornar uma string, n\u00e3o echo.<\/p>\n<pre><code>function awp_gutenberg_slider_render($attributes, $content) {\n    return 'Slider render comes here.';\n}<\/code><\/pre>\n<p>Voltaremos \u00e0 fun\u00e7\u00e3o de renderiza\u00e7\u00e3o do PHP no final deste tutorial. Agora \u00e9 hora de passar para o Javascript!<\/p>\n<h2>Registre um bloco personalizado do Gutenberg em Javascript<\/h2>\n<p>Vamos abrir nosso <code>block-slider.js<\/code>arquivo fonte. Neste ponto, iniciarei o script (<code>npm run start<\/code>) para transformar tudo o que fizermos neste arquivo no arquivo de compila\u00e7\u00e3o \u00e0 medida que avan\u00e7amos. Precisamos registrar o bloco usando <code>[registerBlockType](https:\/\/developer.wordpress.org\/block-editor\/developers\/block-api\/block-registration\/)()<\/code>. Confira o link para ver todos os argumentos poss\u00edveis.<\/p>\n<p>Como decidimos <code>register_block_type()<\/code>no PHP, nosso bloco se chama <code>awp\/slider<\/code>. Tamb\u00e9m queremos adicionar dois atributos ao bloco, conforme mencionado anteriormente: um para o ID do termo selecionado e outro para o n\u00famero de slides.<\/p>\n<p>Eu gosto de adicionar a funcionalidade de alinhamento de blocos tamb\u00e9m. Ele ser\u00e1 adicionado automaticamente adicionando &#8216; <code>align<\/code>&#8216; ao <code>supports<\/code>objeto. Se voc\u00ea quiser todos os alinhamentos de bloco, basta definir <code>align<\/code>como true. No entanto, um controle deslizante alinhado \u00e0 esquerda ou \u00e0 direita n\u00e3o faz muito sentido, ent\u00e3o definirei os tipos espec\u00edficos de alinhamentos de bloco que este bloco suporta: &quot;Alinhar ao centro&quot; (&#8216; <code>center<\/code>&#8216;), &quot;Largura ampla&quot; (&#8216; <code>wide<\/code>&#8216;) e &quot; Largura total&quot; (&#8216; <code>full<\/code>&#8216;) Al\u00e9m disso, para definir um alinhamento padr\u00e3o e torn\u00e1-lo acess\u00edvel a partir do PHP, adiciono &#8216; <code>align<\/code>&#8216; como atributo ao nosso bloco.<\/p>\n<p>Defino o argumento do bloco <code>edit<\/code>para um componente separado que criaremos a seguir. E finalmente a <code>save<\/code>fun\u00e7\u00e3o simplesmente retorna <code>null<\/code>, pois este \u00e9 um bloco din\u00e2mico.<\/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>Precisamos definir o componente para a <code>edit<\/code>propriedade. Antes do c\u00f3digo de registro eu defino um componente de fun\u00e7\u00e3o <code>BlockEdit<\/code>que simplesmente renderiza a <code>div<\/code>e a <code>Placeholder<\/code>com algum texto fict\u00edcio.<\/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>\u00e9 um bom componente para renderizar uma \u00e1rea para configura\u00e7\u00f5es \u2013 e n\u00e3o necessariamente para a renderiza\u00e7\u00e3o real de um bloco. Dentro do <code>Placeholder<\/code>componente \u00e9 onde renderizamos uma lista de termos para escolher.<\/p>\n<p>Neste ponto, nosso bloco deve estar dispon\u00edvel no WordPress Gutenberg! Vamos criar um novo post, adicionar um novo bloco e encontrar nosso bloco dentro da categoria Comum. Esta \u00e9 a apar\u00eancia do nosso bloco atualmente:<\/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: Criar um Slider como um Bloco Gutenberg Din\u00e2mico\"><\/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: Criar um Slider como um Bloco Gutenberg Din\u00e2mico\"><\/a><\/p>\n<h2>Adicionando configura\u00e7\u00f5es do Inspetor<\/h2>\n<p>Vamos adicionar algumas configura\u00e7\u00f5es ao Inspetor (barra lateral direita do editor). Como mencionado, nosso bloco tem apenas uma configura\u00e7\u00e3o; n\u00famero de slides. \u00c9 aqui que eu recomendo que voc\u00ea adicione mais configura\u00e7\u00f5es para o seu bloco de controle deslizante. Lembre-se de registrar atributos para cada configura\u00e7\u00e3o adicionada.<\/p>\n<p>Para adicionar algo ao Inspector usamos o componente <code>[InspectorControls](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/block-editor\/src\/components\/inspector-controls)<\/code>( <code>wp.blockEditor<\/code>). Dentro n\u00f3s renderizamos um <code>[PanelBody](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/panel#panelbody)<\/code>( <code>wp.components<\/code>) para adicionar uma nova se\u00e7\u00e3o recolh\u00edvel. Em seguida, simplesmente renderizamos um <code>[RangeControl](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/range-control)<\/code>( <code>wp.components<\/code>) para criar uma configura\u00e7\u00e3o de entrada para escolher o n\u00famero de slides. Definimos o m\u00ednimo como 1 e o m\u00e1ximo como 10. Conectamos o evento <code>value<\/code>and <code>onChange<\/code>ao 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>Com o c\u00f3digo acima, devemos agora obter uma boa se\u00e7\u00e3o com um controle deslizante de intervalo para definir o n\u00famero de slides.<\/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: Criar um Slider como um Bloco Gutenberg Din\u00e2mico\"><\/a><\/p>\n<p>Mais uma vez, recomendo que voc\u00ea brinque adicionando mais configura\u00e7\u00f5es ao seu controle deslizante. A pr\u00f3xima etapa \u00e9 criar o elemento para renderizar uma lista de categorias para escolher.<\/p>\n<h2>Criando um componente de sele\u00e7\u00e3o de categoria<\/h2>\n<p>Para manter nosso c\u00f3digo organizado e reutiliz\u00e1vel, vamos criar o componente seletor de categoria em um arquivo separado. Dentro da pasta build eu crio um novo arquivo <code>awp-category-picker.js<\/code>.<\/p>\n<p>Dentro deste arquivo, definimos um componente que percorrer\u00e1 todas as categorias atualmente no WordPress e as renderizar\u00e1 de alguma forma. Para obter categorias, precisamos envolv\u00ea-lo dentro de um chamado componente de ordem superior, que fornecer\u00e1 ao nosso componente o que precisamos por meio de adere\u00e7os. Para isso vamos usar <code>[withSelect](https:\/\/developer.wordpress.org\/block-editor\/packages\/packages-data\/#withSelect)<\/code>. Dentro <code>withSelect<\/code>podemos fazer um pedido para buscar todas as categorias no WordPress usando o seletor de loja <code>[select](https:\/\/developer.wordpress.org\/block-editor\/packages\/packages-data\/#select)()<\/code>. Podemos usar:<\/p>\n<pre><code>select('core').getEntityRecords('taxonomy', '&lt;category_slug&gt;', &lt;args&gt;)<\/code><\/pre>\n<p>para buscar todos os termos no slug de taxonomia fornecido. Se voc\u00ea n\u00e3o estiver familiarizado com os componentes e seletores de ordem superior no WordPress Gutenberg, tenho uma postagem que explica esse conceito com mais detalhes: <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/criar-bloco-personalizado-do-gutenberg-parte-10-buscando-postagens-e-componentes-de-ordem-superior\/\" title=\"Criar um bloco personalizado do Gutenberg \u2013 Parte 10: Buscando postagens e componentes de ordem superior\">Criar um bloco personalizado do Gutenberg \u2013 Parte 10: Buscando postagens e componentes de ordem superior<\/a>.<\/p>\n<p>Como precisamos exportar um componente desse arquivo, colocamos a combina\u00e7\u00e3o de <code>withSelect<\/code>e nosso componente definido na <code>export default<\/code>instru\u00e7\u00e3o. Nosso <code>CategorySelect<\/code>componente simplesmente retorna uma div com algum texto fict\u00edcio para que possamos ver que funciona. O <code>withSelect<\/code>deve fornecer o prop &#8216; <code>terms<\/code>&#8216; to <code>CategorySelect<\/code>. Eu adicionei um <code>console.log()<\/code>neste prop para que possamos 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>A \u00faltima coisa que precisamos fazer \u00e9 importar e usar esse componente seletor de categoria em nosso bloco personalizado.<\/p>\n<p>De volta <code>block-slider.js<\/code>, primeiro precisamos importar o componente no topo do arquivo. E dentro do nosso <code>Placeholder<\/code>componente n\u00f3s simplesmente renderizamos o 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>Com o c\u00f3digo acima, seu bloco agora deve renderizar a div do <code>CategorySelect<\/code>componente. Se voc\u00ea abrir o Console em seu navegador, tamb\u00e9m dever\u00e1 ver alguns logs. Lembre-se de que <code>withSelect<\/code>\u00e9 uma consulta ass\u00edncrona, o que significa que pode renderizar v\u00e1rias vezes. A(s) primeira(s) vez(es) que os termos prop s\u00e3o <code>null<\/code>. Mas o(s) \u00faltimo(s) log(s) deve(m) terminar com uma s\u00e9rie de termos de categoria.<\/p>\n<p>Excelente! Vamos continuar trabalhando com nosso <code>CategorySelect<\/code>componente e fazer com que ele realmente renderize a lista de termos permitindo que o usu\u00e1rio selecione um!<\/p>\n<h3>Renderizando uma lista de termos para escolher<\/h3>\n<p>H\u00e1 muitas maneiras de renderizar uma lista de op\u00e7\u00f5es em que o usu\u00e1rio pode selecionar um item. Se voc\u00ea quiser algo realmente simples, poder\u00e1 renderizar um menu suspenso de sele\u00e7\u00e3o padr\u00e3o (<code>[SelectControl](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/select-control)<\/code>). Depende inteiramente de voc\u00ea. Optei por uma abordagem mais limpa e agrad\u00e1vel usando <code>[MenuGroup](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/menu-group)<\/code>( <code>wp.components<\/code>) e <code>[MenuItem](https:\/\/github.com\/WordPress\/gutenberg\/tree\/master\/packages\/components\/src\/menu-item)<\/code>( <code>wp.components<\/code>).<\/p>\n<p>Dentro de um <code>MenuGroup<\/code>componente, precisamos percorrer o <code>props.terms<\/code>array e, para cada item, queremos exibir um <code>MenuItem<\/code>componente renderizando o nome do termo. E \u00e9 claro que s\u00f3 queremos renderizar isso se <code>props.terms<\/code>realmente contiver algo (solicita\u00e7\u00e3o ass\u00edncrona, lembra?).<\/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>Dei ao <code>MenuGroup<\/code>componente uma classe personalizada, pois precisaremos direcionar isso com CSS. E eu configurei o suporte <code>role<\/code>para <code>MenuItem<\/code>&#8216; <code>menuitemradio<\/code>&#8216; para garantir que apenas um possa ser escolhido de cada vez. Por padr\u00e3o, funcionam como checkboxes, permitindo a escolha de v\u00e1rios itens.<\/p>\n<p>Com o c\u00f3digo acima, nosso bloco deve agora (ap\u00f3s um pequeno segundo) renderizar uma boa lista de todas as categorias em sua inst\u00e2ncia do WordPress.<\/p>\n<p>Voc\u00ea pode notar que nosso bloco se expandir\u00e1 para conter todas as categorias. Se estivermos em uma inst\u00e2ncia do WordPress com muitas categorias, isso rapidamente se tornar\u00e1 um problema. Queremos ter certeza de que o seletor \u00e9 um cont\u00eainer de altura m\u00e1xima que recebe uma barra de rolagem vertical se houver muitas categorias. \u00c9 aqui que entra nosso arquivo CSS.<\/p>\n<p>Em nosso <code>editor-block-slider.css<\/code>arquivo adicione:<\/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 tem como alvo o interior do <code>div<\/code>nosso <code>MenuGroup<\/code>e garante que nunca ultrapasse 200px. Se o conte\u00fado <code>MenuGroup<\/code>ficar maior (mais categorias), ele mostrar\u00e1 uma barra de rolagem vertical. Este \u00e9 o m\u00ednimo de CSS para o nosso bloco, mas \u00e9 claro que voc\u00ea pode adicionar mais CSS se quiser.<\/p>\n<p>A \u00faltima coisa que precisamos corrigir em nosso seletor de categoria \u00e9 a funcionalidade de mostrar o item selecionado atualmente e permitir que o usu\u00e1rio selecione um termo da lista. Para isso precisamos passar alguns adere\u00e7os para este componente do nosso bloco.<\/p>\n<p>Em <code>block-slider.js<\/code>n\u00f3s precisamos passar o termo selecionado atual (valor do atributo <code>termId<\/code>) e uma fun\u00e7\u00e3o para atualizar o termo selecionado (<code>setAttributes<\/code>) como props para nosso componente seletor de categoria.<\/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>No c\u00f3digo acima na linha <code>#6<\/code>definimos uma fun\u00e7\u00e3o que simplesmente atualiza o atributo <code>termId<\/code>. Passamos este nome de fun\u00e7\u00e3o como prop para <code>CategorySelect<\/code>at line <code>#17<\/code>. E na linha <code>#16<\/code>passamos o valor atual de <code>termId<\/code>. Com podemos atualizar nosso <code>CategorySelect<\/code>componente para refletir o item escolhido, e permitir que o usu\u00e1rio realmente escolha um termo.<\/p>\n<p>De volta <code>awp-category-picker.js<\/code>, adicionamos alguns novos adere\u00e7os ao <code>MenuItem<\/code>. Retornamos <code>true<\/code>or <code>false<\/code>para a prop <code>isSelected<\/code>se o ID do termo atual \u00e9 ou n\u00e3o o mesmo que o atual selecionado. Iniciamos a <code>selectTerm<\/code>fun\u00e7\u00e3o no <code>onClick<\/code>evento, passando o termo ID. E para tornar visual o item selecionado, adicionamos condicionalmente um \u00edcone antes de cada item.<\/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>Com isso, nosso seletor de categoria deve ficar assim:<\/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: Criar um Slider como um Bloco Gutenberg Din\u00e2mico\"><\/a><\/p>\n<p>A lista deve marcar claramente o termo selecionado com um \u00edcone de verifica\u00e7\u00e3o, e voc\u00ea pode clicar em qualquer termo para selecion\u00e1-lo.<\/p>\n<p>Isso foi tudo para a parte do editor e do Javascript! O que resta agora \u00e9 a renderiza\u00e7\u00e3o do frontend, que faremos em PHP.<\/p>\n<h2>Renderize o bloco din\u00e2mico em PHP<\/h2>\n<p>Antes de mergulharmos na fun\u00e7\u00e3o de renderiza\u00e7\u00e3o, vamos cuidar de algumas coisas primeiro.<\/p>\n<p>Primeiro, precisamos enfileirar o script cycle2 no frontend para que nosso c\u00f3digo deslizante realmente se transforme em um controle deslizante. Fazemos isso com uma fun\u00e7\u00e3o simples ligada a <code>wp_enqueue_scripts<\/code>. Ajuste o abaixo se voc\u00ea optou por outro script de controle 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>Em segundo lugar, queremos retornar \u00e0 <code>register_block_type()<\/code>chamada da fun\u00e7\u00e3o. Quando lidamos com blocos din\u00e2micos, definitivamente devemos adicionar um novo argumento; <code>attributes<\/code>. Neste argumento definimos todos os atributos que definimos <code>registerBlockType<\/code>em Javascript, incluindo seus padr\u00f5es. Se n\u00e3o o fizermos, nem todos os atributos estar\u00e3o dispon\u00edveis em nosso retorno de chamada de renderiza\u00e7\u00e3o. Se um atributo foi deixado inalterado no editor de blocos, o atributo e seu valor n\u00e3o estar\u00e3o dispon\u00edveis no array de atributos no PHP. Ent\u00e3o eu recomendo que voc\u00ea sempre tenha o cuidado de adicionar o <code>attributes<\/code>array \u00e0 fun\u00e7\u00e3o PHP <code>register_block_type()<\/code>quando voc\u00ea trabalha com blocos din\u00e2micos. Para o nosso bloco ficaria assim:<\/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>Agora voltamos \u00e0 nossa fun\u00e7\u00e3o de renderiza\u00e7\u00e3o de retorno de chamada <code>awp_gutenberg_slider_render()<\/code>. A sa\u00edda depende completamente de voc\u00ea, especialmente se voc\u00ea optou por usar outro script de controle deslizante. O abaixo \u00e9 um exemplo simples.<\/p>\n<p>A ideia principal \u00e9 verificar se um termo foi escolhido ou n\u00e3o (<code>$attributes['termId']<\/code>). Se estiver preenchido, criamos um <code>[WP_Query](https:\/\/developer.wordpress.org\/reference\/classes\/wp_query\/)()<\/code>com argumentos para o n\u00famero de posts (<code>$attributes['numSlides']<\/code>) e o ID da categoria selecionada. Em seguida, \u00e9 uma quest\u00e3o de gerar o HTML adequado para o cycle2 funcionar, fazer um loop sobre as postagens e exibir suas imagens em destaque como slides.<\/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>Observe como eu adiciono a classe de alinhamento de bloco adequada na linha <code>#12<\/code>. O resultado deve ser um controle deslizante das imagens em destaque. Tenha em mente que este \u00e9 um exemplo b\u00e1sico que tem algumas falhas. Por exemplo, buscamos os \u00faltimos tr\u00eas posts da categoria selecionada. Mas supondo que um deles n\u00e3o tenha uma imagem em destaque, o controle deslizante exibir\u00e1 apenas duas postagens.<\/p>\n<p>A coisa importante a lembrar \u00e9 retornar uma string e n\u00e3o eco\u00e1-la. Eu tamb\u00e9m recomendo usar algum tipo de funcionalidade de modelagem em seu tema para renderiza\u00e7\u00f5es de blocos din\u00e2micos como esses. Pode rapidamente tornar-se confuso consertar e construir HTML como uma string.<\/p>\n<h2>Palavras finais<\/h2>\n<p>Este tutorial mostrou como criar um bloco WordPress Gutenberg din\u00e2mico personalizado onde voc\u00ea renderiza seu conte\u00fado de front-end em PHP. E voc\u00ea viu como usar o componente de ordem superior <code>withSelect<\/code>para consultar todos os termos de categoria e um m\u00e9todo para exibir uma lista selecion\u00e1vel.<\/p>\n<p>Todo o c\u00f3digo acima \u00e9 escrito o mais simples poss\u00edvel. Eu apenas adicionei o m\u00ednimo absoluto de configura\u00e7\u00f5es. O controle deslizante funciona, mas geralmente voc\u00ea quer mais \u2013 por exemplo, fazer os links dos slides, mostrar os t\u00edtulos das postagens, as setas do controle deslizante ou a op\u00e7\u00e3o de personalizar a velocidade ou outras configura\u00e7\u00f5es do controle deslizante. A ideia \u00e9 mostrar o b\u00e1sico e facilitar a extens\u00e3o, a constru\u00e7\u00e3o e a mudan\u00e7a para atender \u00e0s necessidades do seu projeto.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Um tutorial sobre como criar um bloco din\u00e2mico WordPress Gutenberg com withSelect e renderiza\u00e7\u00e3o PHP. O resultado final \u00e9 um controle 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":[898,898,722,722,941,941,1110,816,816,846,846,867,867],"tags":[1170],"class_list":["post-233878","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-gutenberg-8","category-n-a","category-plug-ins","category-tutoriais","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/233878","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=233878"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/233878\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/151907"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=233878"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=233878"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=233878"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}