Indtil videre har vi dækket, hvordan man arbejder med data fra en ekstern API i en tilpasset WordPress-blok. Vi gik gennem processen med hente disse data til brug på frontend af et WordPress-websted, og hvordan man gengiv det direkte i WordPress Block Editor når du placerer blokken i indhold. Denne gang skal vi slå bro mellem disse to artikler ved at tilslutte os blokeditorens kontrolpanel for at oprette en brugergrænseflade til indstillinger for den blok, vi lavede.
Arbejde med eksterne API'er i WordPress-blokke
Du kender kontrolpanelet, jeg henviser til, ikke? Det er det panel til højre, der indeholder post- og blokindstillinger i blokeditoren.
Kan du se det røde fremhævede område? Det er kontrolpanelet. En afsnitsblok er i øjeblikket valgt, og indstillingerne for den vises i panelet. Vi kan ændre stilarter, farve, typografi ... en række ting!
Nå, det er præcis, hvad vi gør denne gang. Vi skal lave kontrolelementerne for indstillingerne af den fodboldrangeringsblokke, som vi arbejdede på i de sidste to artikler. Sidste gang lavede vi en knap i vores blok, der henter de eksterne data til fodboldranglisten. Vi kendte allerede den URL og de endepunkter, vi havde brug for. Men hvad nu hvis vi ønsker at hente rangering for et andet land? Eller måske en anden liga? Hvad med data fra en anden sæson?
Vi har brug for formularkontrol til at gøre det. Vi kunne gøre brug af interaktive React-komponenter - f.eks Reager-Vælg — for at gennemse de forskellige API-indstillinger, der er tilgængelige for at parse disse data. Men det er der ikke behov for, da WordPress leveres med en masse kernekomponenter, som vi kobler direkte ind i!
dokumentation for disse komponenter - kaldet InspectorControls
— bliver bedre i WordPress Block Editor Håndbog. Det bliver endnu bedre med tiden, men i mellemtiden har vi også WordPress Gutenberg historiebog , WordPress Gutenberg-komponenter websteder for yderligere hjælp.
API-arkitekturen
Inden vi kobler os på noget, er det en god idé at kortlægge, hvad det er, vi har brug for i første omgang. Jeg har kortlagt strukturen af de RapidAPI-data, vi henter, så vi ved, hvad der er tilgængeligt for os:
Sæsoner og lande er to endepunkter på øverste niveau, der knytter sig til et ligaslutpunkt. Derfra har vi resten af de data, vi allerede bruger til at udfylde rangeringstabellen. Så det, vi vil gøre, er at oprette indstillinger i WordPress Block Editor, der filtrerer dataene efter sæson, land og liga, og derefter overfører de filtrerede data til ranglisten. Det giver os mulighed for at droppe blokeringen på en hvilken som helst WordPress-side eller post og vise variationer af dataene i blokken.
For at få stillingen skal vi først få ligaerne. Og for at få ligaerne skal vi først have landene og/eller sæsonerne. Du kan se de forskellige endepunkter i RapidAPI-dashboardet.
Der er forskellige kombinationer af data, som vi kan bruge til at udfylde ranglisten, og du har måske en præference for, hvilke data du ønsker. Af hensyn til denne artikel vil vi oprette følgende muligheder i panelet med blokindstillinger:
- Vælg land
- Vælg Liga
- Vælg Sæson
Så har vi en knap til at indsende disse valg og hente de relevante data og sende dem til rangeringstabellen.
Indlæs og gem en liste over lande
Vi kan ikke vælge, hvilket land vi vil have data for, hvis vi ikke har en liste over lande at vælge imellem. Så vores første opgave er at få fat i en liste over lande fra RapidAPI.
Det ideelle er at hente listen over lande, når blokken rent faktisk bruges i siden eller indlæggets indhold. Der er ingen grund til at hente noget, hvis blokken ikke er i brug. Fremgangsmåden ligner meget, hvad vi gjorde i den første artikel, forskellen er, at vi bruger et andet API-slutpunkt og forskellige attributter til at gemme listen over returnerede lande. Der er andre WordPress måder at hente data på, f.eks api-hent, men det er uden for rammerne af, hvad vi laver her.
Vi kan enten inkludere landelisten manuelt efter at have kopieret den fra API-dataene, eller vi kan bruge en separat API eller et separat bibliotek til at udfylde landene. Men den API, vi bruger, har allerede en liste over lande, så jeg ville bare bruge et af dets endepunkter. Lad os sørge for, at den første landeliste indlæses, når blokken indsættes på siden eller postindhold i blokeditoren:
// 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));
}, []);
Vi har en tilstandsvariabel til at gemme listen over lande. Dernæst skal vi importere en komponent fra @wordpress/blok-editor pakke kaldet InspectorControls
det er der, hvor alle de komponenter, vi skal bruge for at oprette vores indstillingskontroller, er placeret.
import { InspectorControls } from "@wordpress/block-editor";
Pakkens GitHub repo gør et godt stykke arbejde med at forklare InspectorControls
. I vores eksempel kan vi bruge det til at styre API-dataindstillingerne som Land, Liga og Sæson. Her er en forhåndsvisning, så du får en idé om den brugergrænseflade, vi laver:
Og når disse valg er foretaget i blokindstillingerne, bruger vi dem i blokkens Edit
funktion:
{ countriesList && (
)}
Her sørger jeg for, at vi bruger betinget gengivelse, så funktionen kun indlæser komponenten efter listen over lande er indlæst. Hvis du undrer dig over det LeagueSettings
komponent, det er en brugerdefineret komponent, jeg har oprettet i en separat components
undermappe i blokken, så vi kan få en renere og mere organiseret Edit
funktion i stedet for hundredvis af linjer med landedata, der skal håndteres i en enkelt fil.
Vi kan importere det til edit.js
fil som denne:
import { LeagueSettings } from "./components/LeagueSettings";
Dernæst videregiver vi de nødvendige rekvisitter til LeagueSettings
komponent fra forælderen Edit
komponent, så vi kan få adgang til tilstandsvariabler og attributter fra LeagueSettings
barn komponent. Det kan vi også gøre med andre metoder som f.eks Context API for at undgå propboring, men det, vi har lige nu, passer perfekt til det, vi laver.
De andre dele af Edit
funktion kan også konverteres til komponenter. For eksempel kan ligaens stillingskode sættes i en separat komponent - som måske LeagueTable.js
— og derefter importeret ligesom vi importerede LeagueSettings
ind i Edit
funktion.
LeagueSettings.js
fil
Inde LeagueSettings
er ligesom en anden Reaktionskomponent hvorfra vi kan destrukturere rekvisitterne fra den overordnede komponent. Jeg vil bruge tre tilstandsvariable og en yderligere leagueID
stat, fordi vi skal udtrække ID'et fra league
objekt:
const [country, setCountry] = useState(null);
const [league, setLeague] = useState(null);
const [season, setSeason] = useState(null);
const [leagueID, setLeagueID] = useState(null);
Den første ting vi skal gøre er at importere PanelBody
komponent fra @wordpress/block-editor-pakken:
import { PanelBody } from "@wordpress/block-editor";
...og inkludere det i vores return
fungere:
Der er andre panel tags og attributter — Det er bare min personlige præference at bruge disse. Ingen af de andre er påkrævet... men se på alle komponenterne vi har mulighed for at lave et indstillingspanel! Jeg kan godt lide enkelheden i PanelBody
til vores brugssag. Det udvider og kollapser for at afsløre dropdown-indstillingerne for blokken, og det er det.
Apropos det, vi har et valg at træffe for disse valg. Vi kunne bruge SelectControl
komponent eller en ComboBoxControl
, som dokumenterne beskriver som "en forbedret version af en SelectControl
, med tilføjelsen af at være i stand til at søge efter muligheder ved hjælp af et søgeinput." Det er rart for os, fordi listen over lande kan blive temmelig lang, og brugerne vil enten kunne lave en søgeforespørgsel eller vælge fra en liste.
Her er et eksempel på, hvordan en ComboboxControl
kunne fungere for vores landeliste:
handleCountryChange(value) }
onInputChange={ (inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
ComboboxControl
er konfigurerbar i den forstand, at vi kan anvende forskellige størrelser for kontrollens etiket og værdier:
{
value: 'small',
label: 'Small',
},
Men vores API-data er ikke i denne syntaks, så vi kan konvertere countriesList
array, der kommer fra den overordnede komponent, når blokken er inkluderet:
let setupCountrySelect;
setupCountrySelect = countriesList.map((country) => {
return {
label: country.name,
value: country.name,
};
});
Når et land er valgt fra ComboboxControl
, ændres landeværdien, og vi filtrerer dataene i overensstemmelse hermed:
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));
}
Bemærk, at jeg bruger yderligere tre tilstandsvariabler til at håndtere ændringer, når landevalget ændres:
const [filteredCountryOptions, setFilteredCountryOptions] = useState(setupCountrySelect);
const [filteredLeagueOptions, setFilteredLeagueOptions] = useState(null);
const [filteredSeasonOptions, setFilteredSeasonOptions] = useState(null);
Hvad med de andre indstillingsmuligheder?
Jeg vil vise koden, som jeg brugte til de andre indstillinger, men alt det gør er at tage normale tilfælde i betragtning, mens jeg definerer fejl for specielle tilfælde. For eksempel vil der være fejl i nogle lande og ligaer, fordi:
- der er ingen stillinger for nogle ligaer, og
- nogle ligaer har stilling, men de er ikke i en enkelt tabel.
Dette er ikke en JavaScript- eller React-tutorial, så jeg vil lade dig håndtere de særlige tilfælde for den API, du planlægger at bruge:
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);
}
Indsendelse af indstillingsvalg
I sidste artikel, lavede vi en knap i blokeditoren, der henter friske data fra API'et. Der er ikke mere behov for det nu, hvor vi har indstillinger. Nå, vi har brug for det - bare ikke hvor det er i øjeblikket. I stedet for at have det direkte i blokken, der er gengivet i blokeditoren, flytter vi det til vores PanelBody
komponent for at indsende indstillingsvalgene.
Så ind igen 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 && (
)
}
)}
Her er resultatet!
Vi er et rigtig godt sted med vores blok. Vi kan gengive det i blok-editoren og frontenden af webstedet. Vi kan hente data fra en ekstern API baseret på et udvalg af indstillinger, vi har lavet, som filtrerer dataene. Det er ret funktionelt!
Men der er en anden ting, vi skal tackle. Lige nu, når vi gemmer siden eller indlægget, der indeholder blokken, nulstilles de indstillinger, vi valgte for blokeringen. Med andre ord gemmes disse valg ikke nogen steder. Der er lidt mere arbejde for at gøre disse valg vedvarende. Det er der, vi planlægger at tage hen i den næste artikel, så følg med.