Creación de una interfaz de usuario de configuración para un bloque de WordPress personalizado PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Creación de una interfaz de usuario de configuración para un bloque personalizado de WordPress

Hasta ahora, hemos cubierto cómo trabajar con datos de una API externa en un bloque personalizado de WordPress. Recorrimos el proceso de obteniendo esos datos para usarlos en el front-end de un sitio de WordPress, y cómo renderízalo directamente en el editor de bloques de WordPress al colocar el bloque en el contenido. Esta vez, uniremos esos dos artículos conectándonos al panel de control del editor de bloques para crear una interfaz de usuario de configuración para el bloque que creamos.

Trabajar con API externas en bloques de WordPress

Conoces el panel de control al que me refiero, ¿verdad? Es ese panel a la derecha que contiene la configuración de publicación y bloqueo en el editor de bloques.

Creación de una interfaz de usuario de configuración para un bloque personalizado de WordPress

¿Ves esa área resaltada en rojo? Ese es el panel de control. Un bloque de párrafo está actualmente seleccionado y su configuración se muestra en el panel. Podemos cambiar estilos, color, tipografía… ¡muchas cosas!

Bueno, eso es exactamente lo que estamos haciendo esta vez. Vamos a crear los controles para la configuración del bloque Football Rankings en el que trabajamos en los últimos dos artículos. La última vez, creamos un botón en nuestro bloque que busca los datos externos para las clasificaciones de fútbol. Ya sabíamos la URL y los puntos finales que necesitábamos. Pero, ¿qué pasa si queremos obtener la clasificación de un país diferente? ¿O tal vez una liga diferente? ¿Qué hay de los datos de una temporada diferente?

Necesitamos controles de formulario para hacer eso. Podríamos hacer uso de componentes React interactivos, como Reaccionar-Seleccionar — para navegar a través de las diversas opciones de API que están disponibles para analizar esos datos. ¡Pero no hay necesidad de eso ya que WordPress viene con un montón de componentes principales a los que nos conectamos directamente!

El documentación para estos componentes, llamados InspectorControls - está mejorando en el Manual del editor de bloques de WordPress. Eso mejorará aún más con el tiempo, pero mientras tanto, también tenemos la Libro de cuentos de Gutenberg de WordPress y Componentes de WordPress Gutenberg sitios para obtener ayuda adicional.

La arquitectura de la API

Antes de engancharnos a algo, es una buena idea trazar un mapa de lo que necesitamos en primer lugar. He mapeado la estructura de los datos de RapidAPI que estamos obteniendo para que sepamos lo que está disponible para nosotros:

Diagrama de flujo que conecta los puntos finales de la API para los datos de bloque personalizados de WordPress que se obtienen.
Créditos: API-Fútbol

Las temporadas y los países son dos puntos finales de nivel superior que se asignan a un punto final de ligas. A partir de ahí, tenemos el resto de los datos que ya estamos usando para completar la tabla de clasificación. Entonces, lo que queremos hacer es crear configuraciones en el Editor de bloques de WordPress que filtren los datos por temporada, país y liga, y luego pasar esos datos filtrados a la tabla de clasificación. Eso nos da la capacidad de soltar el bloque en cualquier página o publicación de WordPress y mostrar variaciones de los datos en el bloque.

Para obtener la clasificación, primero debemos obtener las ligas. Y para obtener las ligas, primero necesitamos obtener los países y/o las temporadas. Puede ver los diversos puntos finales en el panel de RapidAPI.

Pantalla completa para el tablero de Rapid API que visualiza los datos de la API.
Creación de una interfaz de usuario de configuración para un bloque personalizado de WordPress

Hay diferentes combinaciones de datos que podemos usar para completar las clasificaciones, y es posible que tenga una preferencia por los datos que desea. Por el bien de este artículo, vamos a crear las siguientes opciones en el panel de configuración del bloque:

  • Elige país
  • Elige Liga
  • Elige Temporada

Luego tendremos un botón para enviar esas selecciones y obtener los datos relevantes y pasarlos a la tabla de clasificación.

Cargar y almacenar una lista de países

No podemos seleccionar de qué país queremos datos si no tenemos una lista de países para elegir. Entonces, nuestra primera tarea es obtener una lista de países de RapidAPI.

Lo ideal es obtener la lista de países cuando el bloque se usa realmente en la página o en el contenido de la publicación. No hay necesidad de buscar nada si el bloque no está en uso. El enfoque es muy similar al que hicimos en el primer articulo, la diferencia es que estamos utilizando un punto final de API diferente y diferentes atributos para almacenar la lista de países devueltos. Hay otras formas de WordPress para obtener datos, como api-buscar, pero eso está fuera del alcance de lo que estamos haciendo aquí.

Podemos incluir la lista de países manualmente después de copiarla de los datos de la API, o podemos usar una API o biblioteca separada para completar los países. Pero la API que estamos usando ya tiene una lista de países, así que solo usaría uno de sus puntos finales. Asegurémonos de que la lista inicial de países se cargue cuando el bloque se inserte en la página o publique contenido en el editor de bloques:

// 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));
}, []);

Tenemos una variable de estado para almacenar la lista de países. A continuación, vamos a importar un componente del @wordpress/editor-de-bloques paquete llamado InspectorControls que es donde se encuentran todos los componentes que necesitamos para crear nuestros controles de configuración.

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

Los paquetes Repositorio GitHub hace un buen trabajo explicando InspectorControls. En nuestro ejemplo, podemos usarlo para controlar la configuración de datos de la API, como País, Liga y Temporada. Aquí hay una vista previa para que tengas una idea de la interfaz de usuario que estamos creando:

La interfaz de usuario de configuración personalizada para el bloque de WordPress que muestra las tres opciones de configuración para el bloque personalizado y un botón azul para obtener los datos.
Creación de una interfaz de usuario de configuración para un bloque personalizado de WordPress

Y una vez que esas selecciones se hacen en la configuración del bloque, las usamos en el bloque Edit función:


  { countriesList && (
    
  )}

Aquí, me aseguro de que estamos usando la representación condicional para que la función solo cargue el componente después de la lista de países está cargada. Si te estás preguntando sobre eso LeagueSettings componente, es un componente personalizado que creé en un separado components subcarpeta en el bloque para que podamos tener una más limpia y organizada Edit función en lugar de cientos de líneas de datos de países para tratar en un solo archivo.

Estructura de archivos para el directorio de bloques que muestra el archivo actual.
Creación de una interfaz de usuario de configuración para un bloque personalizado de WordPress

Podemos importarlo en el edit.js archivo como este:

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

A continuación, estamos pasando los accesorios requeridos al LeagueSettings componente del padre Edit componente para que podamos acceder a las variables de estado y atributos desde el LeagueSettings componente hijo. También podemos hacerlo con otros métodos como el API de contexto para evitar la perforación puntal, pero lo que tenemos ahora es perfectamente adecuado para lo que estamos haciendo.

Las otras partes del Edit La función también se puede convertir en componentes. Por ejemplo, el código de clasificación de la liga se puede colocar dentro de un componente separado, como tal vez LeagueTable.js - y luego importó como importamos LeagueSettings en el Edit función.

Dentro del LeagueSettings.js presentar

LeagueSettings es como otro Reaccionar componente a partir del cual podemos desestructurar los accesorios del componente principal. Voy a utilizar tres variables de estado y una adicional leagueID state porque vamos a extraer el ID del league :

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

Lo primero que vamos a hacer es importar el PanelBody componente del paquete @wordpress/block-editor:

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

…e incluirlo en nuestro return función:

Existen otras etiquetas y atributos del panel - es solo mi preferencia personal usar estos. Ninguno de los otros es necesario... pero mira todos los componentes tenemos disponible para hacer un panel de ajustes! Me gusta la sencillez de la PanelBody para nuestro caso de uso. Se expande y contrae para revelar la configuración desplegable para el bloque y eso es todo.

Hablando de eso, tenemos una opción para hacer esas selecciones. Podríamos usar el SelectControl componente o un ComboBoxControl, que los documentos describen como "una versión mejorada de un SelectControl, con la adición de poder buscar opciones usando una entrada de búsqueda”. Eso es bueno para nosotros porque la lista de países podría ser bastante larga y los usuarios podrán realizar una consulta de búsqueda o seleccionar de una lista.

He aquí un ejemplo de cómo un ComboboxControl podría funcionar para nuestra lista de países:

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

El ComboboxControl es configurable en el sentido de que podemos aplicar diferentes tamaños para la etiqueta y los valores del control:

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

Pero nuestros datos API no están en esta sintaxis, por lo que podemos convertir el countriesList matriz que proviene del componente principal cuando se incluye el bloque:

let setupCountrySelect;

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

Cuando se selecciona un país de la ComboboxControl, el valor del país cambia y filtramos los datos en consecuencia:

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));
}

Tenga en cuenta que estoy usando otras tres variables de estado para manejar los cambios cuando cambia la selección del país:

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

¿Qué pasa con las otras opciones de configuración?

Mostraré el código que usé para las otras configuraciones, pero todo lo que hace es tener en cuenta los casos normales al definir errores para casos especiales. Por ejemplo, habrá errores en algunos países y ligas porque:

  • no hay clasificaciones para algunas ligas, y
  • algunas ligas tienen clasificaciones pero no están en una sola tabla.

Este no es un tutorial de JavaScript o React, así que te dejaré manejar los casos especiales de la API que planeas 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);
}

Envío de las selecciones de configuración

En último artículo, creamos un botón en el editor de bloques que obtiene datos nuevos de la API. Ya no es necesario ahora que tenemos configuraciones. Bueno, lo necesitamos, pero no donde está actualmente. En lugar de tenerlo directamente en el bloque que se representa en el editor de bloques, lo moveremos a nuestro PanelBody componente para enviar las selecciones de configuración.

Entonces, de vuelta 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 && (
        
      )
    }
    
  
)}

¡Aquí está el resultado!

Estamos en un muy buen lugar con nuestro bloque. Podemos renderizarlo en el editor de bloques y en el front-end del sitio. Podemos obtener datos de una API externa en función de una selección de configuraciones que creamos que filtran los datos. ¡Es bastante funcional!

Pero hay otra cosa que tenemos que abordar. En este momento, cuando guardamos la página o publicación que contiene el bloque, la configuración que seleccionamos para el reinicio del bloque. En otras palabras, esas selecciones no se guardan en ningún lado. Hay un poco más de trabajo para que esas selecciones sean persistentes. Ahí es donde planeamos ir en el próximo artículo, así que estad atentos.

Sello de tiempo:

Mas de Trucos CSS