Erstellen einer Einstellungs-Benutzeroberfläche für einen benutzerdefinierten WordPress-Block PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Erstellen einer Einstellungs-UI für einen benutzerdefinierten WordPress-Block

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.

Erstellen einer Einstellungs-UI für einen benutzerdefinierten WordPress-Block

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:

Flussdiagramm, das die API-Endpunkte für die abgerufenen benutzerdefinierten WordPress-Blockdaten verbindet.
Kredit: API-Fußball

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.

Vollbild für das Rapid API-Dashboard, das die API-Daten visualisiert.
Erstellen einer Einstellungs-UI für einen benutzerdefinierten WordPress-Block

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:

Die Benutzeroberfläche für benutzerdefinierte Einstellungen für den WordPress-Block mit den drei Einstellungsoptionen für den benutzerdefinierten Block und einer blauen Schaltfläche zum Abrufen der Daten.
Erstellen einer Einstellungs-UI für einen benutzerdefinierten WordPress-Block

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.

Dateistruktur für das Blockverzeichnis mit der aktuellen Datei.
Erstellen einer Einstellungs-UI für einen benutzerdefinierten WordPress-Block

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.

Im Inneren der LeagueSettings.js Datei

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.

Zeitstempel:

Mehr von CSS-Tricks