Houve alguns novos tutoriais surgindo aqui no CSS-Tricks para trabalhar com blocos do WordPress. Um deles é uma introdução ao desenvolvimento de blocos do WordPress e é um bom lugar para aprender o que são blocos e registrá-los no WordPress para uso em páginas e posts.
Embora o básico do bloco seja bem abordado nesse post, quero dar mais um passo à frente. Você vê, nesse artigo, aprendemos a diferença entre renderizar blocos no WordPress Block Editor de back-end e renderizá-los no tema de front-end. O exemplo foi um simples Pullquote Block que renderizava conteúdo e estilos diferentes em cada extremidade.
Vamos mais longe e veja como usar conteúdo dinâmico em um bloco do WordPress. Mais especificamente, vamos buscar dados de uma API externa e renderizá-los no front-end quando um bloco específico for solto no Editor de blocos.
Vamos construir um bloco que gera dados que mostram futebol (er, futebol) classificações extraídas de Api-Futebol.
Há mais de uma maneira de integrar uma API com um bloco do WordPress! Como o artigo sobre noções básicas de blocos já percorreu o processo de fazer um bloco do zero, vamos simplificar as coisas usando o @wordpress/create-block
pacote para inicializar nosso trabalho e estruturar nosso projeto.
Inicializando nosso plugin de bloco
Primeiras coisas primeiro: vamos criar um novo projeto a partir da linha de comando:
npx @wordpress/create-block football-rankings
Eu normalmente iniciaria um projeto como esse criando os arquivos do zero, mas parabéns à equipe do WordPress Core por este utilitário útil!
Uma vez que a pasta do projeto foi criada pelo comando, tecnicamente temos um bloco WordPress totalmente funcional registrado como um plugin. Então, vamos em frente e solte a pasta do projeto no wp-content/plugins
diretório em que você instalou o WordPress (provavelmente é melhor trabalhar em um ambiente local), faça login no administrador do WordPress e ative-o na tela Plugins.
Agora que nosso bloco está inicializado, instalado e ativado, vá em frente e abra a pasta do projeto em /wp-content/plugins/football-rankings
. Você vai querer cd
lá da linha de comando também para garantir que possamos continuar o desenvolvimento.
Estes são os únicos arquivos nos quais precisamos nos concentrar no momento:
edit.js
index.js
football-rankings.php
Os outros arquivos do projeto são importantes, é claro, mas não são essenciais neste momento.
Revisando a origem da API
Já sabemos que estamos usando Api-Futebol que chega até nós cortesia de API rápida. Felizmente, o RapidAPI tem um painel que gera automaticamente os scripts necessários que precisamos para buscar os dados da API para a classificação da Premier League de 2021.
Se você quiser dar uma olhada na estrutura JSON, você pode gerar uma representação visual com JSON Crack.
edit.js
lima
Buscando dados do Vou envolver o código RapidAPI dentro de um Reagir useEffect()
gancho com uma matriz de dependência vazia para que seja executada apenas uma vez quando a página for carregada. Dessa forma, evitamos que o WordPress chame a API toda vez que o Block Editor for renderizado novamente. Você pode verificar isso usando wp.data.subscribe()
se você se importa.
Aqui está o código onde estou importando useEffect()
, em seguida, envolvendo-o ao redor do fetch()
código fornecido pelo RapidAPI:
/**
* The edit function describes the structure of your block in the context of the
* editor. This represents what the editor will render when the block is used.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
*
* @return {WPElement} Element to render.
*/
import { useEffect } from "@wordpress/element";
export default function Edit(props) {
const { attributes, setAttributes } = props;
useEffect(() => {
const options = {
method: "GET",
headers: {
"X-RapidAPI-Key": "Your Rapid API key",
"X-RapidAPI-Host": "api-football-v1.p.rapidapi.com",
},
};
fetch("https://api-football-v1.p.rapidapi.com/v3/standings?season=2021&league=39", options)
.then( ( response ) => response.json() )
.then( ( response ) => {
let newData = { ...response };
setAttributes( { data: newData } );
console.log( "Attributes", attributes );
})
.catch((err) => console.error(err));
}, []);
return (
{ __( "Standings loaded on the front end", "external-api-gutenberg" ) }
);
}
Observe que eu deixei o return
função praticamente intacta, mas incluímos uma nota que confirma que as classificações de futebol são renderizadas no front-end. Novamente, vamos nos concentrar apenas no front-end neste artigo - também podemos renderizar os dados no Block Editor, mas deixaremos isso para outro artigo para manter o foco.
Armazenando dados da API no WordPress
Agora que estamos buscando dados, precisamos armazená-los em algum lugar no WordPress. É aqui que o attributes.data
objeto vem a calhar. Estamos definindo o data.type
como object
uma vez que os dados são buscados e formatados como JSON. Certifique-se de que você não tenha nenhum outro tipo ou então o WordPress não salvará os dados, nem lançará nenhum erro para você depurar.
Definimos tudo isso em nosso index.js
arquivo:
registerBlockType( metadata.name, {
edit: Edit,
attributes: {
data: {
type: "object",
},
},
save,
} );
OK, então o WordPress agora sabe que os dados RapidAPI que estamos buscando são um objeto. Se abrirmos um novo rascunho de postagem no WordPress Block Editor e salvarmos a postagem, os dados agora serão armazenados no banco de dados. De fato, se pudermos ver isso no wp_posts.post_content
campo se abrirmos o banco de dados do site no phpMyAdmin, Sequel Pro, Adminer ou qualquer ferramenta que você use.
Saída de dados JSON no front-end
Existem várias maneiras de gerar os dados no front-end. A forma que vou mostrar pega os atributos que estão armazenados no banco de dados e os passa como parâmetro através do render_callback
funcionar em nosso football-rankings.php
arquivo.
Eu gosto de manter uma separação de preocupações, então como eu faço isso é adicionar dois novos arquivos ao plugin do bloco build
pasta: frontend.js
e frontend.css
(você pode criar um frontend.scss
arquivo no src
diretório que compilou para CSS no build
diretório). Desta forma, os códigos back-end e front-end são separados e os football-rankings.php
arquivo é um pouco mais fácil de ler.
/explanation Voltando à introdução ao desenvolvimento de blocos do WordPress, existem editor.css
e style.css
arquivos para back-end e estilos compartilhados entre o front-end e o back-end, respectivamente. Adicionando frontend.scss
(que compila para frontend.css
, posso isolar estilos que são destinados apenas ao front-end.
Antes de nos preocuparmos com esses novos arquivos, veja como os chamamos football-rankings.php
:
/** * 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/ */ function create_block_football_rankings_block_init() { register_block_type( __DIR__ . '/build', array( 'render_callback' => 'render_frontend' )); } add_action( 'init', 'create_block_football_rankings_block_init' ); function render_frontend($attributes) { if( !is_admin() ) { wp_enqueue_script( 'football_rankings', plugin_dir_url( __FILE__ ) . '/build/frontend.js'); wp_enqueue_style( 'football_rankings', plugin_dir_url( __FILE__ ) . '/build/frontend.css' ); // HIGHLIGHT 15,16,17,18 } ob_start(); ?>
RankLogoTeam nameGPGWGDGLGFGAPtsLast 5 games
<?php return ob_get_clean();
}Já que estou usando o
render_callback()
método para os atributos, vou lidar com o enfileiramento manualmente, assim como o O Manual do Editor de Blocos sugere. Isso está contido no!is_admin()
condição, e está enfileirando os dois arquivos para que evitemos enfileirar enquanto usamos a tela do editor.Agora que temos dois novos arquivos que estamos chamando, precisamos ter certeza de que estamos dizendo
npm
para compilá-los. Então, faça isso empackage.json
, Nascripts
seção:"scripts": { "build": "wp-scripts build src/index.js src/frontend.js", "format": "wp-scripts format", "lint:css": "wp-scripts lint-style", "lint:js": "wp-scripts lint-js", "packages-update": "wp-scripts packages-update", "plugin-zip": "wp-scripts plugin-zip", "start": "wp-scripts start src/index.js src/frontend.js" },
Outra forma de incluir os arquivos é defini-los nos metadados do bloco contidos em nosso
block.json
arquivo, como observado na introdução ao desenvolvimento de blocos:"viewScript": [ "file:./frontend.js", "example-shared-view-script" ], "style": [ "file:./frontend.css", "example-shared-style" ],
A única razão pela qual estou indo com o
package.json
método é porque eu já estou fazendo uso dorender_callback()
método.Renderizando os dados JSON
Na parte de renderização, estou me concentrando apenas em um único bloco. De um modo geral, você deseja segmentar vários blocos no front-end. Nesse caso, você precisa usar
document.querySelectorAll()
com o ID específico do bloco.Basicamente, vou esperar a janela carregar e pegar dados para alguns objetos-chave do JSON e aplicá-los a alguma marcação que os renderize no front-end. Eu também vou converter o
attributes
data para um objeto JSON para que seja mais fácil ler o JavaScript e definir os detalhes de JSON para HTML para itens como o logotipo da liga de futebol, logotipos de times e estatísticas.A coluna “Últimos 5 jogos” mostra o resultado dos últimos cinco jogos de uma equipe. Eu tenho que alterar manualmente os dados para isso, pois os dados da API estão em um formato de string. Convertê-lo em um array pode ajudar a usá-lo em HTML como um elemento separado para cada uma das últimas cinco partidas de uma equipe.
import "./frontend.scss"; // Wait for the window to load window.addEventListener( "load", () => { // The code output const dataEl = document.querySelector( ".data pre" ).innerHTML; // The parent rankings element const tableEl = document.querySelector( ".league-table" ); // The table headers const tableHeaderEl = document.querySelector( "#league-standings .header" ); // Parse JSON for the code output const dataJSON = JSON.parse( dataEl ); // Print a little note in the console console.log( "Data from the front end", dataJSON ); // All the teams let teams = dataJSON.data.response[ 0 ].league.standings[ 0 ]; // The league logo let leagueLogoURL = dataJSON.data.response[ 0 ].league.logo; // Apply the league logo as a background image inline style tableHeaderEl.style.backgroundImage = `url( ${ leagueLogoURL } )`; // Loop through the teams teams.forEach( ( team, index ) => { // Make a div for each team const teamDiv = document.createElement( "div" ); // Set up the columns for match results const { played, win, draw, lose, goals } = team.all; // Add a class to the parent rankings element teamDiv.classList.add( "team" ); // Insert the following markup and data in the parent element teamDiv.innerHTML = `
${ index + 1 }${ team.team.name }`; // Stringify the last five match results for a team const form = team.form.split( "" ); // Loop through the match results form.forEach( ( result ) => { // Make a div for each result const resultEl = document.createElement( "div" ); // Add a class to the div resultEl.classList.add( "result" ); // Evaluate the results resultEl.innerText = result; // If the result a win if ( result === "W" ) { resultEl.classList.add( "win" ); // If the result is a draw } else if ( result === "D" ) { resultEl.classList.add( "draw" ); // If the result is a loss } else { resultEl.classList.add( "lost" ); } // Append the results to the column teamDiv.querySelector( ".form-history" ).append( resultEl ); }); tableEl.append( teamDiv ); }); });${ played }${ win }${ draw }${ lose }${ goals.for }${ goals.against }${ team.points }No que diz respeito ao estilo, você é livre para fazer o que quiser! Se você quiser algo para trabalhar, tenho um conjunto completo de estilos que você pode usar como ponto de partida.
Eu estilizei coisas em SCSS desde o
@wordpress/create-block
pacote o suporta fora da caixa. Correnpm run start
na linha de comando para observar os arquivos SCSS e compilá-los para CSS ao salvar. Alternativamente, você pode usarnpm run build
em cada salvamento para compilar o SCSS e construir o resto do pacote de plugins.Ver SCSS
body { background: linear-gradient(to right, #8f94fb, #4e54c8); } .data pre { display: none; } .header { display: grid; gap: 1em; padding: 10px; grid-template-columns: 1fr 1fr 3fr 4fr 3fr; align-items: center; color: white; font-size: 16px; font-weight: 600; background-repeat: no-repeat; background-size: contain; background-position: right; } .frontend#league-standings { width: 900px; margin: 60px 0; max-width: unset; font-size: 16px; .header { .stats { display: flex; gap: 15px; & > div { width: 30px; } } } } .league-table { background: white; box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px; padding: 1em; .position { width: 20px; } .team { display: grid; gap: 1em; padding: 10px 0; grid-template-columns: 1fr 1fr 3fr 4fr 3fr; align-items: center; } .team:not(:last-child) { border-bottom: 1px solid lightgray; } .team-logo img { width: 30px; } .stats { display: flex; gap: 15px; } .stats > div { width: 30px; text-align: center; } .form-history { display: flex; gap: 5px; } .form-history > div { width: 25px; height: 25px; text-align: center; border-radius: 3px; font-size: 15px; } .form-history .win { background: #347d39; color: white; } .form-history .draw { background: gray; color: white; } .form-history .lost { background: lightcoral; color: white; } }
Aqui está a demonstração!
Confira - acabamos de criar um plug-in de bloco que busca dados e os renderiza no front-end de um site WordPress.
Encontramos uma API,
fetch()
-ed dados dele, salvou-o no banco de dados do WordPress, analisou-o e aplicou-o a alguma marcação HTML para exibir no front-end. Nada mal para um único tutorial, certo?Novamente, podemos fazer o mesmo para que os rankings sejam renderizados no Editor de Blocos, além do front-end do tema. Mas espero que manter isso focado no front-end mostre como a busca de dados funciona em um bloco do WordPress e como os dados podem ser estruturados e renderizados para exibição.