Bisher haben wir behandelt, wie man mit Daten aus einer externen API in einem benutzerdefinierten WordPress-Block arbeitet. Wir haben den Prozess des Abrufens dieser Daten für die Verwendung im Frontend einer WordPress-Site durchlaufen und wie man sie direkt im WordPress Block Editor rendert, wenn der Block in den Inhalt eingefügt wird. Diesmal werden wir diese beiden Artikel verbinden, 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
- Daten im Frontend rendern
- Daten im Backend rendern
- Erstellung einer benutzerdefinierten Einstellungs-UI (Sie sind hier!)
- Benutzerdefinierte Block-Einstellungen speichern
- Arbeiten mit Live-API-Daten (bald verfügbar)
Sie wissen, welches Bedienfeld ich meine, oder? Es ist dieses Feld auf der rechten Seite, das Post- und Blockeinstellungen im Blockeditor enthält.

Sehen Sie diesen rot hervorgehobenen Bereich? Das ist das Bedienfeld. Ein Absatzblock ist derzeit ausgewählt und die Einstellungen dafür werden im Feld angezeigt. Wir können Stile, Farben, Typografie ändern... eine Reihe von Dingen!
Nun, genau das machen wir diesmal. Wir erstellen die Steuerelemente für die Einstellungen des Football Rankings Blocks, an dem wir in den letzten beiden Artikeln gearbeitet haben. Letztes Mal haben wir eine Schaltfläche in unserem Block erstellt, die die externen Daten für die Fußballranglisten abruft. Wir kannten bereits die URL und die Endpunkte, die wir benötigten. Aber was ist, wenn wir die Rangliste für ein anderes Land abrufen möchten? Oder vielleicht eine andere Liga? Wie wäre es mit Daten aus einer anderen Saison?
Dafür brauchen wir Formularsteuerelemente. Wir könnten interaktive React-Komponenten verwenden – wie React-Select – um die verschiedenen verfügbaren API-Optionen zum Parsen der Daten zu durchsuchen. Aber das ist nicht nötig, da WordPress viele Kernkomponenten mitbringt, in die wir uns direkt einklinken können!
Die Dokumentation für diese Komponenten – genannt InspectorControls – wird im WordPress Block Editor Handbook immer besser. Das wird mit der Zeit noch besser, aber in der Zwischenzeit haben wir auch das WordPress Gutenberg Storybook und WordPress Gutenberg Components für zusätzliche Hilfe.
Die API-Architektur
Bevor wir uns einklinken, ist es eine gute Idee, zu planen, 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 Top-Level-Endpunkte, die zu einem Ligen-Endpunkt führen. Von dort haben wir den Rest der Daten, die wir bereits verwenden, um die Ranglistentabelle zu füllen. Wir wollen also Einstellungen im WordPress Block Editor erstellen, die die Daten nach Saison, Land und Liga filtern und dann diese gefilterten Daten an die Ranglistentabelle weitergeben. Das gibt uns die Möglichkeit, den Block auf jeder WordPress-Seite oder in jedem Beitrag abzulegen und Variationen der Daten im Block anzuzeigen.
Um die Tabellenstände zu erhalten, müssen wir zuerst die Ligen abrufen. Und um die Ligen zu erhalten, müssen wir zuerst die Länder und/oder die Saisons abrufen. Sie können die verschiedenen Endpunkte im RapidAPI-Dashboard einsehen.

Es gibt verschiedene Kombinationen von Daten, die wir zur Füllung der Ranglisten verwenden können, und Sie haben vielleicht eine Präferenz für die Daten, die Sie möchten. Für diesen Artikel werden wir im Einstellungsfenster des Blocks die folgenden Optionen erstellen
- Land wählen
- Liga wählen
- Saison wählen
Dann haben wir eine Schaltfläche, um diese Auswahlen abzuschicken und die relevanten Daten abzurufen und an die Ranglistentabelle zu übergeben.
Liste der Länder laden und speichern
Wir können nicht auswählen, für welches Land wir Daten erhalten möchten, wenn wir keine Liste der Länder haben, aus denen wir wählen können. Unsere erste Aufgabe ist es also, eine Liste der Länder von RapidAPI abzurufen.
Idealerweise rufen wir die Liste der Länder ab, wenn der Block tatsächlich im Seiten- oder Beitragsinhalt verwendet wird. Es gibt keinen Grund, etwas abzurufen, wenn der Block nicht verwendet wird. Der Ansatz ist dem, was wir im ersten Artikel getan haben, sehr ähnlich. Der Unterschied besteht darin, dass wir einen anderen API-Endpunkt und andere Attribute zum Speichern der Liste der zurückgegebenen Länder verwenden. Es gibt andere WordPress-Möglichkeiten, Daten abzurufen, wie api-fetch, 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 von uns verwendete API hat bereits eine Liste von Ländern, daher würde ich einfach einen ihrer Endpunkte verwenden. Stellen wir sicher, dass die anfängliche Länderliste geladen wird, wenn der Block in den Seiten- oder Beitragsinhalt im Blockeditor eingefügt wird
// 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 dem Paket @wordpress/block-editor namens InspectorControls, wo sich alle Komponenten befinden, die wir zum Erstellen unserer Einstellungssteuerelemente benötigen.
import { InspectorControls } from "@wordpress/block-editor";
Das GitHub-Repository des Pakets erklärt InspectorControls gut. In unserem Beispiel können wir es verwenden, um API-Dateneinstellungen wie Land, Liga und Saison zu steuern. Hier ist eine Vorschau, damit Sie eine Vorstellung von der UI bekommen, die wir erstellen

Und sobald diese Auswahlen im Blockeditor getroffen wurden, verwenden wir sie in der Edit-Funktion des Blocks
<InspectorControls>
{ countriesList && (
<LeagueSettings
props={props}
countriesList={ countriesList }
setApiData={ setApiData }
></LeagueSettings>
)}
</InspectorControls>
Hier stelle ich sicher, dass wir bedingtes Rendering verwenden, damit die Funktion die Komponente erst lädt, *nachdem* die Länderliste geladen wurde. Wenn Sie sich über die LeagueSettings-Komponente wundern, handelt es sich um eine benutzerdefinierte Komponente, die ich in einem separaten components-Unterordner im Block erstellt habe, damit wir eine sauberere und besser organisierte Edit-Funktion haben, anstatt Hunderte von Zeilen mit Länderdaten in einer einzigen Datei.

Wir können sie auf diese Weise in die edit.js-Datei importieren
import { LeagueSettings } from "./components/LeagueSettings";
Als Nächstes übergeben wir die erforderlichen Props von der übergeordneten Edit-Komponente an die LeagueSettings-Komponente, damit wir auf die Zustandsvariablen und Attribute von der untergeordneten LeagueSettings-Komponente zugreifen können. Wir können das auch mit anderen Methoden wie der Context API tun, um Prop-Drilling zu vermeiden, aber was wir jetzt haben, ist für das, was wir tun, vollkommen ausreichend.
Die anderen Teile der Edit-Funktion können ebenfalls in Komponenten umgewandelt werden. Zum Beispiel kann der Code für die Ligastände in eine separate Komponente – vielleicht LeagueTable.js – gelegt und dann importiert werden, so wie wir LeagueSettings in die Edit-Funktion importiert haben.
Im LeagueSettings.js-File
LeagueSettings ist wie eine weitere React-Komponente, von der wir die Props von der übergeordneten Komponente destrukturieren können. Ich werde drei Zustandsvariablen und eine zusätzliche leagueID-Zustandsvariable verwenden, da wir die ID aus dem league-Objekt extrahieren werden
const [country, setCountry] = useState(null);
const [league, setLeague] = useState(null);
const [season, setSeason] = useState(null);
const [leagueID, setLeagueID] = useState(null);
Das erste, was wir tun werden, ist die Komponente PanelBody aus dem Paket @wordpress/block-editor zu importieren
import { PanelBody } from "@wordpress/block-editor";
...und sie in unsere return-Funktion einzufügen
<PanelBody title="Data settings" initialOpen={false}></PanelBody>
Es gibt andere Panel-Tags und Attribute – es ist nur meine persönliche Vorliebe, diese zu verwenden. Keine der anderen ist erforderlich... aber sehen Sie sich alle Komponenten an, die uns zur Verfügung stehen, um ein Einstellungsfenster zu erstellen! Ich mag die Einfachheit von PanelBody für unseren Anwendungsfall. Es erweitert und reduziert sich, um die Dropdown-Einstellungen für den Block anzuzeigen, und das war's.
Diesbezüglich haben wir eine Wahl zu treffen. Wir könnten die Komponente SelectControl oder eine ComboBoxControl verwenden, die laut Dokumentation „eine erweiterte Version von SelectControl ist, mit der Möglichkeit, Optionen über ein Suchfeld zu suchen.“ Das ist gut für uns, da die Liste der Länder ziemlich lang werden könnte und die Benutzer entweder eine Suchanfrage durchführen oder aus einer Liste auswählen können.
Hier ist ein Beispiel, wie ein ComboboxControl für unsere Länderliste funktionieren könnte
<ComboboxControl
label="Choose country"
value={country}
options={ filteredCountryOptions }
onChange={ (value) => handleCountryChange(value) }
onInputChange={ (inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
Das ComboboxControl ist konfigurierbar in dem Sinne, dass wir unterschiedliche Größen für das Label und die Werte des Steuerelements anwenden können
{
value: 'small',
label: 'Small',
},
Aber unsere API-Daten sind nicht in dieser Syntax, daher können wir das countriesList-Array, das von der übergeordneten Komponente kommt, wenn der Block eingefügt wird, konvertieren
let setupCountrySelect;
setupCountrySelect = countriesList.map((country) => {
return {
label: country.name,
value: country.name,
};
});
Wenn ein Land aus dem ComboboxControl ausgewählt wird, ä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 drei weitere 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 Einstellungsoptionen?
Ich zeige den Code, den ich für die anderen Einstellungen verwendet habe, aber er berücksichtigt nur normale Fälle und definiert Fehler für Sonderfälle. Zum Beispiel wird es bei einigen Ländern und Ligen Fehler geben, weil
- es keine Tabellenstände für einige Ligen gibt, und
- einige Ligen Tabellenstände haben, diese aber nicht in einer einzigen Tabelle sind.
Dies ist kein JavaScript- oder React-Tutorial, daher überlasse ich Ihnen die Behandlung der Sonderfälle für die API, 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);
}
Übermittlung der Einstellungs-Auswahlen
Im letzten Artikel haben wir eine Schaltfläche im Blockeditor erstellt, die neue Daten von der API abruft. Diese wird jetzt nicht mehr benötigt, da wir Einstellungen haben. Nun, wir brauchen sie – nur nicht dort, wo sie sich gerade befindet. Anstatt sie direkt im im Blockeditor gerenderten Block zu haben, verschieben wir sie in unsere PanelBody-Komponente, um die Einstellungs-Auswahlen zu übermitteln.
Also, zurück in 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>
)
}
</>
</>
)}
Hier ist das Ergebnis!
Wir sind mit unserem Block an einem sehr guten Punkt. Wir können ihn im Blockeditor und im Frontend der Website rendern. Wir können Daten von einer externen API abrufen, basierend auf einer Auswahl von Einstellungen, die wir erstellt haben und die die Daten filtern. Es ist ziemlich funktional!
Aber es gibt noch eine Sache, die wir angehen müssen. Im Moment, wenn wir die Seite oder den Beitrag speichern, der den Block enthält, werden die für den Block ausgewählten Einstellungen zurückgesetzt. Mit anderen Worten, diese Auswahlen werden nirgendwo gespeichert. Es ist noch ein wenig Arbeit nötig, um diese Auswahlen dauerhaft zu machen. Dort werden wir im nächsten Artikel hingehen, also bleiben Sie dran.
Toller Artikel. Ich habe nach einem Artikel gesucht, der erklärt, wie man eine Einstellungs-UI für Blöcke in WordPress erstellt, um sie einem Kollegen zu zeigen. Dies ist der einfachste Prozess, den ich gefunden habe.