Până acum, am abordat cum să lucrați cu date dintr-un API extern într-un bloc WordPress personalizat. Am parcurs procesul de preluând acele date pentru utilizare pe front-end a unui site WordPress și cum redați-l direct în Editorul de blocuri WordPress la plasarea blocului în conținut. De data aceasta, vom conecta aceste două articole prin conectarea la panoul de control al editorului de blocuri pentru a crea o interfață de utilizare de setări pentru blocul pe care l-am creat.
Lucrul cu API-uri externe în blocuri WordPress
Știi panoul de control la care mă refer, nu? Este acel panou din dreapta care conține setările de postare și blocare în editorul de blocuri.
Vedeți acea zonă evidențiată în roșu? Acesta este panoul de control. Un bloc de paragraf este selectat în prezent și setările pentru acesta sunt afișate în panou. Putem schimba stilurile, culoarea, tipografia... o serie de lucruri!
Ei bine, exact asta facem de data asta. Vom crea controalele pentru setările blocului Football Rankings la care am lucrat în ultimele două articole. Ultima dată, am făcut un buton în blocul nostru care preia datele externe pentru clasamentele fotbalistice. Știam deja adresa URL și punctele finale de care aveam nevoie. Dar dacă vrem să obținem clasamentul pentru o altă țară? Sau poate o altă ligă? Ce zici de datele dintr-un sezon diferit?
Avem nevoie de controale de formular pentru a face asta. Am putea folosi componente interactive React - cum ar fi Reacționează-Selectează — pentru a naviga prin diferitele opțiuni API care sunt disponibile pentru a analiza acele date. Dar nu este nevoie de asta, deoarece WordPress este livrat cu o grămadă de componente de bază pe care le conectăm direct!
documentaţie pentru aceste componente — numite InspectorControls
— este din ce în ce mai bine în Manual WordPress Block Editor. Asta se va îmbunătăți în timp, dar între timp, avem și Cartea de povești Gutenberg WordPress și Componentele WordPress Gutenberg site-uri pentru ajutor suplimentar.
Arhitectura API
Înainte de a ne conecta la ceva, este o idee bună să stabilim de ce avem nevoie în primul rând. Am trasat structura datelor RapidAPI pe care le preluăm, astfel încât să știm ce avem la dispoziție:
Sezoanele și țările sunt două puncte finale de nivel superior care se mapează la un punct final al ligii. De acolo, avem restul datelor pe care le folosim deja pentru a completa tabelul de clasare. Așadar, ceea ce vrem să facem este să creăm setări în Editorul de blocuri WordPress care filtrează datele după sezon, țară și ligă, apoi trecem acele date filtrate în tabelul de clasamente. Acest lucru ne oferă posibilitatea de a arunca blocul în orice pagină sau postare WordPress și de a afișa variații ale datelor din bloc.
Pentru a obține clasamentul, trebuie să obținem mai întâi ligile. Și pentru a obține ligile, trebuie mai întâi să obținem țările și/sau sezoanele. Puteți vizualiza diferitele puncte finale în tabloul de bord RapidAPI.
Există diferite combinații de date pe care le putem folosi pentru a popula clasamentele și este posibil să aveți o preferință pentru datele pe care le doriți. De dragul acestui articol, vom crea următoarele opțiuni în panoul de setări pentru blocuri:
- Alege țara
- Alege Liga
- Alegeți Sezon
Apoi vom avea un buton pentru a trimite acele selecții și a prelua datele relevante și a le trece în tabelul de clasare.
Încărcați și stocați o listă de țări
Nu putem selecta pentru ce țară dorim date dacă nu avem o listă de țări din care să alegem. Deci, prima noastră sarcină este să luăm o listă de țări din RapidAPI.
Ideal este să preluați lista țărilor când blocul este de fapt folosit în pagină sau în conținutul postării. Nu este nevoie să preluați nimic dacă blocul nu este în uz. Abordarea este foarte asemănătoare cu ceea ce am făcut noi primul articol, diferența fiind că folosim un punct final API diferit și atribute diferite pentru a stoca lista țărilor returnate. Există și alte moduri WordPress de a prelua date, cum ar fi api-fetch, dar asta este în afara domeniului de aplicare a ceea ce facem noi aici.
Putem include fie lista de țări manual după ce o copiem din datele API, fie putem folosi un API sau o bibliotecă separată pentru a popula țările. Dar API-ul pe care îl folosim are deja o listă de țări, așa că aș folosi doar unul dintre punctele sale finale. Să ne asigurăm că lista inițială de țări se încarcă atunci când blocul este inserat în pagină sau postăm conținut în editorul de blocuri:
// 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));
}, []);
Avem o variabilă de stat pentru a stoca lista de țări. În continuare, vom importa o componentă din @wordpress/block-editor pachetul numit InspectorControls
care este locul în care se află toate componentele de care avem nevoie pentru a ne crea controalele pentru setări.
import { InspectorControls } from "@wordpress/block-editor";
Al pachetului GitHub repo face o treabă bună explicând InspectorControls
. În exemplul nostru, îl putem folosi pentru a controla setările datelor API, cum ar fi Țara, Liga și Sezonul. Iată o previzualizare pentru a vă face o idee despre interfața de utilizare pe care o realizăm:
Și odată ce aceste selecții sunt făcute în setările de bloc, le folosim în ale blocului Edit
funcţie:
{ countriesList && (
)}
Aici, mă asigur că folosim randarea condiționată, astfel încât funcția să încarce doar componenta după se incarca lista tarilor. Dacă te întrebi despre asta LeagueSettings
componentă, este o componentă personalizată pe care am creat-o separat components
subfolder din bloc astfel încât să putem avea un mai curat și mai organizat Edit
funcția în loc de sute de rânduri de date de țară de tratat într-un singur fișier.
Îl putem importa în edit.js
fișier așa:
import { LeagueSettings } from "./components/LeagueSettings";
Apoi, transmitem recuzita necesară către LeagueSettings
componentă de la părinte Edit
componentă astfel încât să putem accesa variabilele de stare și atributele din LeagueSettings
componenta copil. Putem face asta și cu alte metode precum API context pentru a evita forarea prop, dar ceea ce avem acum este perfect potrivit pentru ceea ce facem.
Celelalte părți ale Edit
funcția poate fi, de asemenea, convertită în componente. De exemplu, codul clasamentului ligii poate fi introdus într-o componentă separată - ca poate LeagueTable.js
— și apoi importate la fel cum am importat noi LeagueSettings
în Edit
Funcția.
LeagueSettings.js
fişier
În interiorul LeagueSettings
este la fel ca altul Componenta React din care putem destructura recuzita din componenta părinte. Voi folosi trei variabile de stare și una suplimentară leagueID
stare deoarece vom extrage ID-ul din league
obiect:
const [country, setCountry] = useState(null);
const [league, setLeague] = useState(null);
const [season, setSeason] = useState(null);
const [leagueID, setLeagueID] = useState(null);
Primul lucru pe care îl vom face este să importam PanelBody
componentă din pachetul @wordpress/block-editor:
import { PanelBody } from "@wordpress/block-editor";
… și includeți-l în documentul nostru return
funcţie:
Sunt alte etichete și atribute de panou — este doar preferința mea personală să le folosesc pe acestea. Niciunul dintre ceilalți nu este necesar... dar uita-te la toate componentele avem la dispoziție să facem un panou de setări! Îmi place simplitatea PanelBody
pentru cazul nostru de utilizare. Se extinde și se restrânge pentru a dezvălui setările drop-down pentru bloc și asta este tot.
Apropo de asta, avem de făcut o alegere pentru acele selecții. Am putea folosi SelectControl
componentă sau a ComboBoxControl
, pe care documentele o descriu drept „o versiune îmbunătățită a a SelectControl
, cu plus de posibilitatea de a căuta opțiuni folosind o intrare de căutare.” Acest lucru este frumos pentru noi, deoarece lista de țări ar putea fi destul de lungă, iar utilizatorii vor putea fie să facă o interogare de căutare, fie să selecteze dintr-o listă.
Iată un exemplu despre cum a ComboboxControl
ar putea funcționa pentru lista noastră de țări:
handleCountryChange(value) }
onInputChange={ (inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
ComboboxControl
este configurabil în sensul că putem aplica diferite dimensionări pentru eticheta și valorile controlului:
{
value: 'small',
label: 'Small',
},
Dar datele noastre API nu sunt în această sintaxă, așa că putem converti countriesList
matrice care provine din componenta părinte atunci când blocul este inclus:
let setupCountrySelect;
setupCountrySelect = countriesList.map((country) => {
return {
label: country.name,
value: country.name,
};
});
Când o țară este selectată din ComboboxControl
, valoarea țării se modifică și filtrem datele în consecință:
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));
}
Rețineți că folosesc alte trei variabile de stare pentru a gestiona modificările atunci când selecția țării se schimbă:
const [filteredCountryOptions, setFilteredCountryOptions] = useState(setupCountrySelect);
const [filteredLeagueOptions, setFilteredLeagueOptions] = useState(null);
const [filteredSeasonOptions, setFilteredSeasonOptions] = useState(null);
Cum rămâne cu celelalte opțiuni de setări?
Voi arăta codul pe care l-am folosit pentru celelalte setări, dar tot ceea ce face este să ia în considerare cazurile normale în timp ce definesc erorile pentru cazuri speciale. De exemplu, vor exista erori în unele țări și ligi, deoarece:
- nu există clasamente pentru unele ligi și
- unele ligi au clasamente, dar nu sunt într-o singură masă.
Acesta nu este un tutorial JavaScript sau React, așa că vă voi lăsa să vă ocupați de cazurile speciale pentru API-ul pe care intenționați să îl utilizați:
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);
}
Trimiterea selecțiilor de setări
În Ultimul articol, am creat un buton în editorul de blocuri care preia date proaspete din API. Nu mai este nevoie acum că avem setări. Ei bine, avem nevoie de el – doar că nu este acolo unde este în prezent. În loc să îl avem direct în blocul care este redat în editorul de blocuri, îl vom muta în PanelBody
componentă pentru a trimite selecțiile de setări.
Deci, înapoi înăuntru 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 && (
)
}
)}
Iată rezultatul!
Suntem într-un loc foarte bun cu blocul nostru. Îl putem reda în editorul de blocuri și în front-end-ul site-ului. Putem prelua date dintr-un API extern pe baza unei selecții de setări pe care le-am creat, care filtrează datele. Este al naibii de funcțional!
Dar mai este un lucru pe care trebuie să-l rezolvăm. Chiar acum, când salvăm pagina sau postarea care conține blocul, setările pe care le-am selectat pentru blocare se resetează. Cu alte cuvinte, acele selecții nu sunt salvate nicăieri. Mai este puțină muncă pentru a face aceste selecții persistente. Acolo plănuim să mergem în următorul articol, așa că rămâneți pe fază.