Crear una interfaz de usuario de configuración de bloque de WordPress personalizada | trucos CSS
Hasta ahora, hemos visto cómo trabajar con datos de una API externa en un bloque personalizado de WordPress. Pasamos por el proceso de recuperar estos datos para usarlos en la parte frontal de un sitio de WordPress y cómo mostrarlos directamente en el Editor de bloques de WordPress al colocar el bloque en el contenido. Esta vez conectaremos estos dos artículos conectándonos al Panel de control del editor de bloques para crear una interfaz de usuario con configuraciones para el bloque que hicimos.
Trabajar con API externas en bloques de WordPress
Conoces el panel de control al que me refiero, ¿verdad? Este es el panel de la derecha que contiene la configuración de publicación y bloqueo en el editor de bloques.
¿Ves esa área resaltada en rojo? Este 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. Crearemos los controles para la configuración del bloque Football Rankings en el que trabajamos en los dos últimos artículos. La última vez hicimos un botón en nuestro bloque que busca los datos externos de la clasificación de fútbol. Ya sabíamos la URL y los puntos finales que necesitábamos. Pero, ¿y si queremos recuperar una clasificación para un país diferente? ¿O tal vez para una liga diferente? ¿Qué pasa con los datos de una temporada diferente?
Necesitamos controles de formulario para hacer esto. Podemos usar componentes React interactivos, como Reaccionar-Seleccionar — para explorar las diversas opciones de API disponibles para analizar estos datos. ¡Pero no es necesario, ya que WordPress viene con un montón de componentes principales a los que nos conectamos directamente!
los documentación para estos componentes, los llamados InspectorControls
— mejora en Guía del editor de bloques de WordPressEsto mejorará aún más con el tiempo, pero mientras tanto, también tenemos Libro de cuentos de WordPress Gutenberg y Componentes de WordPress Gutenberg sitios para obtener ayuda adicional.
La arquitectura de la API
Antes de llegar a nada, es una buena idea trazar un mapa de lo que necesitamos primero. Dibujé la estructura de los datos de RapidAPI que recuperamos para que sepamos lo que está disponible para nosotros:
Seasons y Countries son dos puntos finales de nivel superior que se conectan a un punto final de Leagues. A partir de ahí, tenemos el resto de los datos que ya usamos para completar la tabla de clasificación. Entonces, lo que queremos hacer es crear una configuración en el Editor de bloques de WordPress que filtre los datos por temporada, país y liga, y luego pase esos datos filtrados a la tabla de clasificación. Esto nos da la capacidad de colocar el bloque en cualquier página o publicación de WordPress y mostrar variaciones de los datos en el bloque.
Para obtener las clasificaciones, primero debemos obtener las ligas. Y para obtener las ligas, primero debemos obtener los países y/o las temporadas. Puede ver los diferentes puntos finales en el panel de RapidAPI.
Hay diferentes combinaciones de datos que podemos usar para completar las tablas de clasificación, y usted puede tener una preferencia por los datos que desea Para los fines de este artículo, crearemos las siguientes opciones en el panel de configuración del bloque:
- Seleccione un país
- Seleccionar liga
- Seleccionar temporada
Entonces tendremos un botón para enviar estas selecciones y recuperar los datos relevantes y pasarlos a la tabla de clasificación.
Cargar y guardar una lista de países
No podemos elegir de qué país queremos datos si no tenemos una lista de países para elegir. Así que nuestra primera tarea es obtener una lista de países de RapidAPI.
Lo ideal es recuperar la lista de países cuando el bloque se usa realmente en el contenido de la página o publicación. No es necesario extraer nada si el bloque no está en uso. El enfoque es muy similar al que hicimos en el primer artículo, con la diferencia de que usamos un punto final de API diferente y diferentes atributos para almacenar la lista de países devueltos.Hay otras formas de WordPress para recuperar datos, como api-buscarpero eso está más allá 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 esté cargada 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, importaremos un componente de @wordpress/editor de bloques paquete llamado InspectorControls
dónde encontrar todos los componentes que necesitamos para crear nuestros controles de configuración.
import { InspectorControls } from "@wordpress/block-editor";
El paquete repositorio de GitHub hace un buen trabajo explicando InspectorControls
.En nuestro ejemplo, podemos usarlo para controlar la configuración de datos de la API, como el país, la liga y la temporada. Aquí hay una vista previa para tener una idea de la interfaz de usuario que estamos haciendo:
Y una vez que estas selecciones se realizan en la configuración del bloque, las usamos en el bloque Edit
función:
<InspectorControls>
{ countriesList && (
<LeagueSettings
props={props}
countriesList={ countriesList }
setApiData={ setApiData }
></LeagueSettings>
)}
</InspectorControls>
Aquí me aseguro de usar renderizado condicional para que la función solo cargue el componente después la lista de países está cargada Si te estás preguntando sobre esto LeagueSettings
componente, este es un componente personalizado que creé en un componente separado components
subcarpeta en el bloque para que podamos tener una más limpia y organizada Edit
función en lugar de cientos de filas de datos de países para procesar en un solo archivo.
Podemos importarlo en edit.js
archivo como este:
import { LeagueSettings } from "./components/LeagueSettings";
Luego pasamos los accesorios necesarios para LeagueSettings
componente del padre Edit
componente para que podamos acceder a las variables de estado y atributos desde LeagueSettings
también podemos hacer esto con otros métodos como API de contexto para evitar la plataforma de perforación, pero lo que tenemos ahora está perfectamente bien para lo que estamos haciendo.
Las otras partes de Edit
La función también se puede convertir en componentes. Por ejemplo, el código de clasificación de la liga podría colocarse en un componente separado, como tal vez LeagueTable.js
- y luego importado como nosotros importamos LeagueSettings
en Edit
función.
Dentro de LeagueSettings.js
expediente
LeagueSettings
es como otro Reaccionar componentes desde el cual podemos destruir los puntales del componente principal. Usaré tres variables de estado y una adicional leagueID
estado porque recuperaremos la identificación de league
objeto:
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 PanelBody
componente del paquete @wordpress/block-editor:
import { PanelBody } from "@wordpress/block-editor";
… e incluirlo en el nuestro return
función:
<PanelBody title="Data settings" initialOpen={false}></PanelBody>
Hay otras etiquetas y atributos del panel — es mi preferencia personal usar estos. Ninguno de los otros es necesario... pero mira todos los componentes ¡Tenemos disponible para hacer un panel de configuración! Me gusta la simplicidad de 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 estas selecciones. Nosotros podemos usar SelectControl
componente o un ComboBoxControl
que los documentos describen como “una versión mejorada de un SelectControl
con la adición de la capacidad de buscar opciones escribiendo una búsqueda”. Esto es bueno para nosotros porque la lista de países puede ser bastante larga y los usuarios podrán realizar una solicitud de búsqueda o elegir de una lista.
Aquí hay un ejemplo de cómo un ComboboxControl
puede funcionar para nuestra lista de países:
<ComboboxControl
label="Choose country"
value={country}
options={ filteredCountryOptions }
onChange={ (value) => handleCountryChange(value) }
onInputChange={ (inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
los ComboboxControl
es configurable en el sentido de que podemos aplicar diferentes tamaños a la etiqueta y valores del control:
{
value: 'small',
label: 'Small',
},
Pero nuestros datos API no están en esta sintaxis, por lo que podemos convertir 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 ComboboxControl
el valor del estado 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 uso tres variables de estado más para manejar los cambios cuando cambia la selección de 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 la otra configuración, 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 la misma tabla.
Este no es un tutorial de JavaScript o React, así que te dejaré manejar los casos especiales para 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);
}
Enviar la configuración seleccionada
En el último artículo, creamos un botón en el editor de bloques que obtiene nuevos datos de la API. Ya no es necesario después de que tengamos la configuración. Bueno, lo necesitamos, pero no donde está ahora. En vez de tener directamente en el bloque que se renderiza en el editor de bloques, lo moveremos al nuestro PanelBody
componente para enviar la configuración de selección.
Entonces, de vuelta LeagueSettings.js
:
// When countriesList is loaded, show the country combo box
{ countriesList && (
<ComboboxControl
label="Choose country"
value={country}
options={filteredCountryOptions}
onChange={(value) => handleCountryChange(value)}
onInputChange={(inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
)}
// When filteredLeagueOptions is set through handleCountryChange, show league combobox
{ filteredLeagueOptions && (
<ComboboxControl
label="Choose league"
value={league}
options={filteredLeagueOptions}
onChange={(value) => handleLeagueChange(value)}
onInputChange={(inputValue) => {
setFilteredLeagueOptions(
setupLeagueSelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
)}
// When filteredSeasonOptions is set through handleLeagueChange, show season combobox
{ filteredSeasonOptions && (
<>
<ComboboxControl
label="Choose season"
value={season}
options={filteredSeasonOptions}
onChange={(value) => 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 && (
<button className="fetch-data" onClick={() => getData()}>Fetch data</button>
)
}
</>
</>
)}
¡Aquí está el resultado!
Estamos en un muy buen lugar con nuestro bloque. Podemos renderizarlo en el editor de bloques y en la parte frontal del sitio. Podemos recuperar datos de una API externa en función de una selección de configuraciones que hemos creado que filtran los datos. ¡Es funcional como el infierno!
Pero hay otra cosa con la que tenemos que lidiar. En este momento, cuando guardamos la página o publicación que contiene el bloque, se restablecen las configuraciones que elegimos para el bloque. En otras palabras, estas selecciones no se guardan en ningún lado. hay un poco mas trabajar para hacer que estas selecciones sean permanentes. Aquí es donde planeamos ir en el próximo artículo, así que estad atentos.
Deja una respuesta