Criando uma interface de usuário de configurações para um bloco WordPress personalizado PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Criando uma IU de configurações para um bloco personalizado do WordPress

Até agora, abordamos como trabalhar com dados de uma API externa em um bloco personalizado do WordPress. Percorremos o processo de buscar esses dados para uso no front-end de um site WordPress e como renderize-o diretamente no Editor de blocos do WordPress ao colocar o bloco no conteúdo. Desta vez, vamos unir esses dois artigos acessando o painel de controle do editor de blocos para criar uma interface do usuário de configurações para o bloco que criamos.

Trabalhando com APIs externas em blocos do WordPress

Você conhece o painel de controle a que me refiro, certo? É o painel à direita que contém as configurações de postagem e bloco no editor de bloco.

Criando uma IU de configurações para um bloco personalizado do WordPress

Está vendo aquela área destacada em vermelho? Esse é o painel de controle. Um bloco de parágrafo está atualmente selecionado e suas configurações são exibidas no painel. Podemos mudar estilos, cores, tipografia… uma série de coisas!

Bem, isso é exatamente o que estamos fazendo desta vez. Vamos criar os controles para as configurações do bloco Football Rankings que trabalhamos nos últimos dois artigos. Da última vez, fizemos um botão em nosso bloco que busca os dados externos do ranking de futebol. Já sabíamos o URL e os endpoints de que precisávamos. Mas e se quisermos buscar a classificação de um país diferente? Ou talvez uma liga diferente? Que tal dados de uma temporada diferente?

Precisamos de controles de formulário para fazer isso. Poderíamos usar componentes interativos do React — como Reagir-Selecionar — para navegar pelas várias opções de API disponíveis para analisar esses dados. Mas não há necessidade disso, já que o WordPress vem com vários componentes principais aos quais nos conectamos!

A documentação para esses componentes - chamados InspectorControls — está melhorando no Manual do Editor de Blocos WordPress. Isso ficará ainda melhor com o tempo, mas, enquanto isso, também temos o Livro de Histórias de Gutenberg WordPress e Componentes WordPress Gutenberg sites para obter ajuda adicional.

A arquitetura da API

Antes de nos envolvermos em qualquer coisa, é uma boa ideia mapear o que precisamos em primeiro lugar. Mapeei a estrutura dos dados RapidAPI que estamos buscando para sabermos o que está disponível para nós:

Fluxograma que conecta os endpoints da API para os dados de bloco personalizados do WordPress que são buscados.
Crédito: API-Futebol

Temporadas e países são dois endpoints de nível superior que mapeiam para um endpoint de liga. A partir daí, temos o restante dos dados que já estamos usando para preencher a tabela de classificação. Então, o que queremos fazer é criar configurações no Editor de blocos do WordPress que filtrem os dados por Temporada, País e Liga e, em seguida, passar esses dados filtrados para a tabela de classificação. Isso nos dá a capacidade de soltar o bloco em qualquer página ou postagem do WordPress e exibir variações dos dados no bloco.

Para obter a classificação, precisamos primeiro obter as ligas. E para obter as ligas, primeiro precisamos obter os países e/ou as temporadas. Você pode visualizar os vários endpoints no painel RapidAPI.

Tela inteira para o painel Rapid API que visualiza os dados da API.
Criando uma IU de configurações para um bloco personalizado do WordPress

Existem diferentes combinações de dados que podemos usar para preencher as classificações, e você pode ter uma preferência para quais dados deseja. Para este artigo, vamos criar as seguintes opções no painel de configurações do bloco:

  • Escolha o País
  • Escolha a Liga
  • Escolha a temporada

Em seguida, teremos um botão para enviar essas seleções e buscar os dados relevantes e passá-los para a tabela de classificação.

Carregar e armazenar uma lista de países

Não podemos selecionar para qual país queremos dados se não tivermos uma lista de países para escolher. Portanto, nossa primeira tarefa é obter uma lista de países da RapidAPI.

O ideal é buscar a lista de países quando o bloqueio for efetivamente utilizado na página ou no conteúdo do post. Não há necessidade de buscar nada se o bloco não estiver em uso. A abordagem é muito semelhante ao que fizemos em o primeiro artigo, a diferença é que estamos usando um terminal de API diferente e atributos diferentes para armazenar a lista de países retornados. Existem outras maneiras do WordPress para buscar dados, como busca de API, mas isso está fora do escopo do que estamos fazendo aqui.

Podemos incluir a lista de países manualmente depois de copiá-la dos dados da API ou podemos usar uma API ou biblioteca separada para preencher os países. Mas a API que estamos usando já tem uma lista de países, então eu usaria apenas um de seus endpoints. Vamos garantir que a lista inicial de países seja carregada quando o bloco for inserido na página ou postar conteúdo no editor de blocos:

// edit.js
const [countriesList, setCountriesList] = useState(null);

useEffect(() => {
  let countryOptions = {
    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/countries", countryOptions)
    .then( (response) => response.json() )
    .then( (response) => {
      let countriesArray = { ...response };
      console.log("Countries list", countriesArray.response);
      setCountriesList(countriesArray.response);
    })
  .catch((err) => console.error(err));
}, []);

Temos uma variável de estado para armazenar a lista de países. Em seguida, vamos importar um componente do @wordpress/editor de blocos pacote chamado InspectorControls que é onde todos os componentes que precisamos para criar nossos controles de configurações estão localizados.

import { InspectorControls } from "@wordpress/block-editor";

do pacote GitHub repo faz um bom trabalho explicando InspectorControls. Em nosso exemplo, podemos usá-lo para controlar as configurações de dados da API, como País, Liga e Temporada. Aqui está uma prévia para que você tenha uma ideia da IU que estamos fazendo:

A IU de configurações personalizadas para o bloco WordPress mostrando as três opções de configurações para o bloco personalizado e um botão azul para buscar os dados.
Criando uma IU de configurações para um bloco personalizado do WordPress

E uma vez que essas seleções são feitas nas configurações do bloco, nós as usamos em o bloco Edit função:


  { countriesList && (
    
  )}

Aqui, estou me certificando de que estamos usando renderização condicional para que a função carregue apenas o componente depois de a lista de países é carregada. Se você está se perguntando sobre isso LeagueSettings componente, é um componente personalizado que criei em um separado components subpasta no bloco para que possamos ter um ambiente mais limpo e organizado Edit função em vez de centenas de linhas de dados de país para lidar em um único arquivo.

Estrutura de arquivo para o diretório de bloco mostrando o arquivo atual.
Criando uma IU de configurações para um bloco personalizado do WordPress

Podemos importá-lo para o edit.js arquivo como este:

import { LeagueSettings } from "./components/LeagueSettings";

Em seguida, estamos passando os adereços necessários para o LeagueSettings componente do pai Edit componente para que possamos acessar as variáveis ​​de estado e atributos do LeagueSettings componente filho. Também podemos fazer isso com outros métodos como o API de contexto para evitar a perfuração de prop, mas o que temos agora é perfeitamente adequado para o que estamos fazendo.

As outras partes do Edit função também pode ser convertida em componentes. Por exemplo, o código de classificação da liga pode ser colocado dentro de um componente separado — como talvez LeagueTable.js — e então importados como nós importamos LeagueSettings no Edit função.

No interior do LeagueSettings.js lima

LeagueSettings é como outro Componente de reação a partir do qual podemos desestruturar os props do componente pai. Vou usar três variáveis ​​de estado e uma variável adicional leagueID estado porque vamos extrair o ID do league objeto:

const [country, setCountry] = useState(null);
const [league, setLeague] = useState(null);
const [season, setSeason] = useState(null);
const [leagueID, setLeagueID] = useState(null);

A primeira coisa que vamos fazer é importar o PanelBody componente do pacote @wordpress/block-editor:

import { PanelBody } from "@wordpress/block-editor";

…e incluí-lo em nosso return função:

Tem outras tags e atributos do painel - é apenas minha preferência pessoal usar esses. Nenhum dos outros é necessário... mas veja todos os componentes temos disponível para fazer um painel de configurações! Eu gosto da simplicidade do PanelBody para o nosso caso de uso. Ele se expande e se fecha para revelar as configurações suspensas do bloco e é isso.

Falando nisso, temos uma escolha a fazer para essas seleções. Poderíamos usar o SelectControl componente ou um ComboBoxControl, que os documentos descrevem como “uma versão aprimorada de um SelectControl, além de poder pesquisar opções usando uma entrada de pesquisa.” Isso é bom para nós porque a lista de países pode ficar muito longa e os usuários poderão fazer uma consulta de pesquisa ou selecionar em uma lista.

Aqui está um exemplo de como um ComboboxControl poderia funcionar para nossa lista de países:

 handleCountryChange(value) }
  onInputChange={ (inputValue) => {
    setFilteredCountryOptions(
      setupCountrySelect.filter((option) =>
        option.label
          .toLowerCase()
          .startsWith(inputValue.toLowerCase())
      )
    );
  }}
/>

A ComboboxControl é configurável no sentido de que podemos aplicar tamanhos diferentes para o rótulo e os valores do controle:

{
  value: 'small',
  label: 'Small',
},

Mas nossos dados de API não estão nessa sintaxe, então podemos converter o countriesList array que vem do componente pai quando o bloco é incluído:

let setupCountrySelect;

setupCountrySelect = countriesList.map((country) => {
  return {
    label: country.name,
    value: country.name,
  };
});

Quando um país é selecionado na ComboboxControl, o valor do país muda e filtramos os dados de acordo:

function handleCountryChange(value) {
  // Set state of the country 
  setCountry(value); 

  // League code from RapidAPI
  const options = {
    method: "GET",
    headers: {
      "X-RapidAPI-Key": "Your RapidAPI key",
      "X-RapidAPI-Host": "api-football-v1.p.rapidapi.com",
    },
  };

  fetch(`https://api-football-v1.p.rapidapi.com/v3/leagues?country=${value}`, options)
    .then((response) => response.json())
    .then((response) => {
      return response.response;
    })
    .then((leagueOptions) => {
      // Set state of the league variable
      setLeague(leagueOptions);

      // Convert it as we did for Country options
      setupLeagueSelect = leagueOptions.map((league) => {
        return {
          label: league.league.name,
          value: league.league.name,
        };
      });
      setFilteredLeagueOptions(setupLeagueSelect);
    })
  .catch((err) => console.error(err));
}

Observe que estou usando outras três variáveis ​​de estado para lidar com as mudanças quando a seleção do país muda:

const [filteredCountryOptions, setFilteredCountryOptions] = useState(setupCountrySelect);
const [filteredLeagueOptions, setFilteredLeagueOptions] = useState(null);
const [filteredSeasonOptions, setFilteredSeasonOptions] = useState(null);

E as outras opções de configuração?

Vou mostrar o código que usei para as outras configurações, mas tudo o que ele faz é levar em consideração os casos normais ao definir erros para casos especiais. Por exemplo, haverá erros em alguns países e ligas porque:

  • não há classificação para algumas ligas, e
  • algumas ligas têm classificações, mas não estão em uma única tabela.

Este não é um tutorial de JavaScript ou React, portanto, deixarei você lidar com os casos especiais da API que planeja usar:

function handleLeagueChange(value) {
  setLeague(value);
  if (league) {
    const selectedLeague = league.filter((el) => {
      if (el.league.name === value) {
        return el;
      }
    });

    if (selectedLeague) {
      setLeague(selectedLeague[0].league.name);
      setLeagueID(selectedLeague[0].league.id);
      setupSeasonSelect = selectedLeague[0].seasons.map((season) => {
        return {
          label: season.year,
          value: season.year,
        };
      });
      setFilteredSeasonOptions(setupSeasonSelect);
    }
  } else {
    return;
  }
}

function handleSeasonChange(value) {
  setSeason(value);
}

Enviando as seleções de configurações

No último artigo, criamos um botão no editor de blocos que busca dados atualizados da API. Não há mais necessidade disso agora que temos configurações. Bem, nós precisamos disso - mas não onde está atualmente. Em vez de tê-lo diretamente no bloco renderizado no editor de blocos, vamos movê-lo para o nosso PanelBody para enviar as seleções de configurações.

Então, de volta LeagueSettings.js:

// When countriesList is loaded, show the country combo box
{ countriesList && (
   handleCountryChange(value)}
    onInputChange={(inputValue) => {
      setFilteredCountryOptions(
        setupCountrySelect.filter((option) =>
          option.label
            .toLowerCase()
            .startsWith(inputValue.toLowerCase())
        )
      );
    }}
  />
)}

// When filteredLeagueOptions is set through handleCountryChange, show league combobox
{ filteredLeagueOptions && (
   handleLeagueChange(value)}
    onInputChange={(inputValue) => {
      setFilteredLeagueOptions(
        setupLeagueSelect.filter((option) =>
          option.label
            .toLowerCase()
            .startsWith(inputValue.toLowerCase())
        )
      );
    }}
  />
)}

// When filteredSeasonOptions is set through handleLeagueChange, show season combobox
{ filteredSeasonOptions && (
  
     handleSeasonChange(value)}
      onInputChange={
          (inputValue) => {
            setFilteredSeasonOptions(
              setupSeasonSelect.filter((option) =>
              option.label
              .toLowerCase()
              .startsWith(inputValue.toLowerCase()
            )
          );
        }
      }
    />

    // When season is set through handleSeasonChange, show the "Fetch data" button
    {
      season && (
        
      )
    }
    
  
)}

Aqui está o resultado!

Estamos em um lugar muito bom com o nosso bloco. Podemos renderizá-lo no editor de blocos e no front-end do site. Podemos buscar dados de uma API externa com base em uma seleção de configurações que criamos que filtram os dados. É muito funcional!

Mas há outra coisa que temos de resolver. Neste momento, quando salvamos a página ou postagem que contém o bloqueio, as configurações que selecionamos para o bloqueio são redefinidas. Em outras palavras, essas seleções não são salvas em nenhum lugar. Há um pouco mais de trabalho para tornar essas seleções persistentes. É para onde planejamos ir no próximo artigo, portanto, fique atento.

Carimbo de hora:

Mais de Truques CSS