Bisher haben wir behandelt, wie man mit Daten von einer externen API in einem benutzerdefinierten WordPress-Block arbeitet. Wir gingen durch den Prozess von Abrufen dieser Daten zur Verwendung am Frontend einer WordPress-Site und wie es geht Rendern Sie es direkt im WordPress-Blockeditor beim Platzieren des Blocks im Inhalt. Dieses Mal werden wir diese beiden Artikel überbrücken, indem wir uns in das Bedienfeld des Blockeditors einklinken, um eine Einstellungs-UI für den von uns erstellten Block zu erstellen.
Arbeiten mit externen APIs in WordPress-Blöcken
Sie kennen das Bedienfeld, auf das ich mich beziehe, oder? Es ist das Feld auf der rechten Seite, das Post- und Blockeinstellungen im Blockeditor enthält.
Sehen Sie den rot markierten Bereich? Das ist das Bedienfeld. Ein Absatzblock ist derzeit ausgewählt und die Einstellungen dafür werden im Bedienfeld angezeigt. Wir können Stile, Farbe, Typografie ändern … eine Reihe von Dingen!
Nun, genau das tun wir dieses Mal. Wir werden die Steuerelemente für die Einstellungen des Fußball-Ranglistenblocks erstellen, an denen wir in den letzten beiden Artikeln gearbeitet haben. Letztes Mal haben wir in unserem Block eine Schaltfläche erstellt, die die externen Daten für die Fußballrangliste abruft. Wir kannten bereits die URL und die Endpunkte, die wir brauchten. Aber was ist, wenn wir das Ranking für ein anderes Land abrufen möchten? Oder vielleicht eine andere Liga? Wie wäre es mit Daten aus einer anderen Saison?
Dazu benötigen wir Formularsteuerelemente. Wir könnten interaktive React-Komponenten verwenden – wie Reagieren-Auswählen — um die verschiedenen API-Optionen zu durchsuchen, die zum Analysieren dieser Daten verfügbar sind. Aber das ist nicht nötig, da WordPress mit einer Reihe von Kernkomponenten ausgeliefert wird, in die wir uns direkt einklinken!
Das Dokumentation für diese Komponenten — genannt InspectorControls
— wird immer besser in der WordPress-Blockeditor-Handbuch. Das wird mit der Zeit noch besser, aber mittlerweile haben wir auch die WordPress Gutenberg-Storybook und WordPress Gutenberg-Komponenten Websites für zusätzliche Hilfe.
Die API-Architektur
Bevor wir uns in irgendetwas einklinken, ist es eine gute Idee, zu ermitteln, was wir überhaupt brauchen. Ich habe die Struktur der RapidAPI-Daten, die wir abrufen, abgebildet, damit wir wissen, was uns zur Verfügung steht:
Saisons und Länder sind zwei Endpunkte der obersten Ebene, die einem Liga-Endpunkt zugeordnet sind. Von dort haben wir den Rest der Daten, die wir bereits verwenden, um die Rangliste zu füllen. Wir wollen also Einstellungen im WordPress-Blockeditor erstellen, die die Daten nach Saison, Land und Liga filtern, und diese gefilterten Daten dann in die Ranglistentabelle weitergeben. Das gibt uns die Möglichkeit, den Block auf jeder WordPress-Seite abzulegen oder Variationen der Daten im Block zu posten und anzuzeigen.
Um die Rangliste zu bekommen, müssen wir zuerst die Ligen bekommen. Und um die Ligen zu bekommen, müssen wir zuerst die Länder und/oder die Jahreszeiten bekommen. Sie können die verschiedenen Endpunkte im RapidAPI-Dashboard anzeigen.
Es gibt verschiedene Kombinationen von Daten, die wir verwenden können, um die Ranglisten zu füllen, und Sie haben möglicherweise eine Präferenz für die gewünschten Daten. Für diesen Artikel werden wir die folgenden Optionen im Blockeinstellungsfenster erstellen:
- Land auswählen
- Wähle Liga
- Wählen Sie Saison
Dann haben wir eine Schaltfläche, um diese Auswahl zu übermitteln und die relevanten Daten abzurufen und sie an die Rangliste weiterzugeben.
Laden und speichern Sie eine Länderliste
Wir können nicht auswählen, für welches Land wir Daten wünschen, wenn wir keine Länderliste zur Auswahl haben. Unsere erste Aufgabe besteht also darin, eine Liste der Länder von RapidAPI abzurufen.
Ideal ist es, die Liste der Länder abzurufen, wenn der Block tatsächlich in der Seite oder im Inhalt des Beitrags verwendet wird. Es ist nicht erforderlich, etwas abzurufen, wenn der Block nicht verwendet wird. Der Ansatz ist dem sehr ähnlich, den wir in gemacht haben der erste Artikel, der Unterschied besteht darin, dass wir einen anderen API-Endpunkt und andere Attribute verwenden, um die Liste der zurückgegebenen Länder zu speichern. Es gibt andere WordPress-Möglichkeiten, um Daten abzurufen, wie z API-Abruf, aber das liegt außerhalb des Rahmens dessen, was wir hier tun.
Wir können die Länderliste entweder manuell einfügen, nachdem wir sie aus den API-Daten kopiert haben, oder wir könnten eine separate API oder Bibliothek verwenden, um die Länder zu füllen. Aber die API, die wir verwenden, hat bereits eine Länderliste, also würde ich einfach einen ihrer Endpunkte verwenden. Stellen wir sicher, dass die anfängliche Länderliste geladen wird, wenn der Block in die Seite eingefügt wird, oder veröffentlichen Sie Inhalte im Blockeditor:
// 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));
}, []);
Wir haben eine Zustandsvariable, um die Liste der Länder zu speichern. Als Nächstes importieren wir eine Komponente aus der @wordpress/block-editor Paket aufgerufen InspectorControls
Hier befinden sich alle Komponenten, die wir zum Erstellen unserer Einstellungssteuerelemente benötigen.
import { InspectorControls } from "@wordpress/block-editor";
Das Paket GitHub Repo macht gute erklärungsarbeit InspectorControls
. In unserem Beispiel können wir damit die API-Dateneinstellungen wie Land, Liga und Saison steuern. Hier ist eine Vorschau, damit Sie sich ein Bild von der Benutzeroberfläche machen können, die wir erstellen:
Und sobald diese Auswahl in den Blockeinstellungen getroffen wurde, verwenden wir sie in des Blocks Edit
Funktion:
{ countriesList && (
)}
Hier stelle ich sicher, dass wir bedingtes Rendering verwenden, damit die Funktion nur die Komponente lädt nachdem die Länderliste wird geladen. Wenn Sie sich darüber wundern LeagueSettings
Komponente, es ist eine benutzerdefinierte Komponente, die ich in einer separaten erstellt habe components
Unterordner im Block, damit wir sauberer und besser organisiert sein können Edit
statt Hunderte von Zeilen mit Länderdaten in einer einzigen Datei zu verwalten.
Wir können es in die importieren edit.js
Datei wie folgt:
import { LeagueSettings } from "./components/LeagueSettings";
Als nächstes übergeben wir die erforderlichen Requisiten an die LeagueSettings
Komponente vom Elternteil Edit
Komponente, damit wir auf die Zustandsvariablen und Attribute von zugreifen können LeagueSettings
untergeordnete Komponente. Wir können das auch mit anderen Methoden wie dem machen Kontext-API Prop Drilling zu vermeiden, aber was wir jetzt haben, ist perfekt geeignet für das, was wir tun.
Die anderen Teile der Edit
Funktion kann auch in Komponenten umgewandelt werden. Zum Beispiel kann der Liga-Platzierungscode in eine separate Komponente eingefügt werden – wie vielleicht LeagueTable.js
– und dann genauso importiert, wie wir importiert haben LeagueSettings
in die Edit
Funktion.
LeagueSettings.js
Datei
Im Inneren der LeagueSettings
ist wie ein anderes Reaktionskomponente aus der wir die Requisiten von der übergeordneten Komponente destrukturieren können. Ich werde drei Zustandsvariablen und eine zusätzliche verwenden leagueID
Zustand, weil wir die ID aus der extrahieren werden league
Objekt:
const [country, setCountry] = useState(null);
const [league, setLeague] = useState(null);
const [season, setSeason] = useState(null);
const [leagueID, setLeagueID] = useState(null);
Als erstes importieren wir die PanelBody
Komponente aus dem Paket @wordpress/block-editor:
import { PanelBody } from "@wordpress/block-editor";
…und nehmen Sie es in unsere auf return
Funktion:
Es gibt andere Panel-Tags und -Attribute – Es ist nur meine persönliche Vorliebe, diese zu verwenden. Keiner der anderen ist erforderlich ... aber schau dir mal alle komponenten an Wir haben die Möglichkeit, ein Einstellungsfeld zu erstellen! Ich mag die Einfachheit der PanelBody
für unseren Anwendungsfall. Es wird erweitert und reduziert, um die Dropdown-Einstellungen für den Block anzuzeigen, und das war's.
Apropos, wir müssen uns für diese Auswahl entscheiden. Wir könnten die gebrauchen SelectControl
Komponente oder ein ComboBoxControl
, die in den Dokumenten als „eine erweiterte Version von a SelectControl
, mit der zusätzlichen Möglichkeit, mithilfe einer Sucheingabe nach Optionen zu suchen.“ Das ist schön für uns, weil die Liste der Länder ziemlich lang werden könnte und die Benutzer entweder eine Suchanfrage stellen oder aus einer Liste auswählen können.
Hier ist ein Beispiel dafür, wie a ComboboxControl
könnte für unsere Länderliste funktionieren:
handleCountryChange(value) }
onInputChange={ (inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
Das ComboboxControl
ist in dem Sinne konfigurierbar, dass wir unterschiedliche Größen für die Beschriftung und die Werte des Steuerelements anwenden können:
{
value: 'small',
label: 'Small',
},
Aber unsere API-Daten sind nicht in dieser Syntax, also können wir die konvertieren countriesList
Array, das von der übergeordneten Komponente stammt, wenn der Block enthalten ist:
let setupCountrySelect;
setupCountrySelect = countriesList.map((country) => {
return {
label: country.name,
value: country.name,
};
});
Wenn ein Land aus der ausgewählt wird ComboboxControl
, ändert sich der Länderwert und wir filtern die Daten entsprechend:
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));
}
Beachten Sie, dass ich weitere drei Zustandsvariablen verwende, um Änderungen zu handhaben, wenn sich die Länderauswahl ändert:
const [filteredCountryOptions, setFilteredCountryOptions] = useState(setupCountrySelect);
const [filteredLeagueOptions, setFilteredLeagueOptions] = useState(null);
const [filteredSeasonOptions, setFilteredSeasonOptions] = useState(null);
Was ist mit den anderen Einstellungsmöglichkeiten?
Ich werde den Code zeigen, den ich für die anderen Einstellungen verwendet habe, aber er berücksichtigt nur Normalfälle, während Fehler für Sonderfälle definiert werden. Beispielsweise wird es in einigen Ländern und Ligen zu Fehlern kommen, weil:
- Für einige Ligen gibt es keine Tabellen, und
- Einige Ligen haben Tabellen, aber sie befinden sich nicht in einer einzigen Tabelle.
Dies ist kein JavaScript- oder React-Tutorial, daher lasse ich Sie die Sonderfälle für die API behandeln, die Sie verwenden möchten:
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);
}
Übermitteln der Einstellungsauswahl
Im letzte Artikelhaben wir im Blockeditor eine Schaltfläche erstellt, die neue Daten von der API abruft. Das ist jetzt, da wir Einstellungen haben, nicht mehr nötig. Nun, wir brauchen es – nur nicht dort, wo es derzeit ist. Anstatt es direkt in dem Block zu haben, der im Blockeditor gerendert wird, verschieben wir es zu unserem PanelBody
Komponente, um die Einstellungsauswahl zu übermitteln.
Also wieder rein 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 && (
)
}
)}
Hier ist das Ergebnis!
Wir sind mit unserem Block sehr gut aufgestellt. Wir können es im Blockeditor und im Frontend der Site rendern. Wir können Daten von einer externen API abrufen, basierend auf einer Auswahl von Einstellungen, die wir erstellt haben, die die Daten filtern. Es ist verdammt funktional!
Aber es gibt eine andere Sache, die wir anpacken müssen. Wenn wir jetzt die Seite oder den Beitrag speichern, der den Block enthält, werden die Einstellungen, die wir für den Block ausgewählt haben, zurückgesetzt. Mit anderen Worten, diese Auswahlen werden nirgendwo gespeichert. Es ist etwas mehr Arbeit erforderlich, um diese Auswahl dauerhaft zu machen. Genau dorthin wollen wir im nächsten Artikel gehen, also bleiben Sie dran.