To date, we’ve lined find out how to work with knowledge from an exterior API in a customized WordPress block. We walked by means of the method of fetching that knowledge to be used on the entrance finish of a WordPress website, and find out how to render it instantly within the WordPress Block Editor when inserting the block in content material. This time, we’re going to bridge these two articles by hooking into the block editor’s management panel to create a settings UI for the block we made.
Working With Exterior APIs in WordPress Blocks
Rendering Information on the Entrance FinishRendering Information on the Again FinishMaking a Customized Settings UI (you’re right here!)Saving Customized Block Settings (coming quickly)
You understand the management panel I’m referring to, proper? It’s that panel on the best that comprises publish and block settings within the block editor.
See that purple highlighted space? That’s the management panel. A Paragraph block is at present chosen and the settings for it are displayed within the panel. We are able to change kinds, coloration, typography… numerous issues!
Nicely, that’s precisely what we’re doing this time round. We’re going to create the controls for the settings of the Soccer Rankings block we labored on within the final two articles. Final time, we made a button in our block that fetches the exterior knowledge for the soccer rankings. We already knew the URL and endpoints we wanted. However what if we wish to fetch rating for a distinct nation? Or perhaps a distinct league? How about knowledge from a distinct season?
We’d like type controls to try this. We might make use of interactive React parts — like React-Choose — to flick through the assorted API choices which are accessible to parse that knowledge. However there’s no want for that since WordPress ships with a bunch of core parts that we hook proper into!
The documentation for these parts — known as InspectorControls — is getting higher within the WordPress Block Editor Handbook. That’ll get even higher over time, however in the meantime, we even have the WordPress Gutenberg Storybook and WordPress Gutenberg Elements websites for extra assist.
The API structure
Earlier than we hook into something, it’s a good suggestion to map out what it’s we’d like within the first place. I’ve mapped out the construction of the RapidAPI knowledge we’re fetching so we all know what’s accessible to us:
Credit score: API-Soccer
Seasons and nations are two top-level endpoints that map to a leagues endpoint. From there, we now have the remainder of the info we’re already utilizing to populate the rankings desk. So, what we wish to do is create settings within the WordPress Block Editor that filter the info by Season, Nation, and League, then go that filtered knowledge into the rankings desk. That provides us the flexibility to drop the block in any WordPress web page or publish and show variations of the info within the block.
With a view to get the standings, we have to first get the leagues. And as a way to get the leagues, we first must get the nations and/or the seasons. You possibly can view the assorted endpoints within the RapidAPI dashboard.
There are completely different combos of knowledge that we will use to populate the rankings, and also you may need a choice for which knowledge you need. For the sake of this text, we’re going to create the next choices within the block settings panel:
Select CountryChoose LeagueChoose Season
Then we’ll have a button to submit these picks and fetch the related knowledge and go them into the rankings desk.
Load and retailer an inventory of nations
We are able to’t choose which nation we wish knowledge for if we don’t have an inventory of nations to select from. So, our first job is to seize an inventory of nations from RapidAPI.
The best factor is to fetch the listing of nations when the block is definitely used within the web page or publish content material. There’s no must fetch something if the block isn’t in use. The strategy is similar to what we did in the primary article, the distinction being that we’re utilizing a distinct API endpoint and completely different attributes to retailer the listing of returned nations. There are different WordPress methods to fetch knowledge, like api-fetch, however that‘s outdoors the scope of what we’re doing right here.
We are able to both embody the nation listing manually after copying it from the API knowledge, or we might use a separate API or library to populate the nations. However the API we’re utilizing already has an inventory of nations, so I’d simply use one in all its endpoints. Let’s be certain that the preliminary nation listing hundreds when the block is inserted into the web page or publish content material within the block editor:
// edit.js
const [countriesList, setCountriesList] = useState(null);
useEffect(() => {
let countryOptions = {
technique: “GET”,
headers: {
“X-RapidAPI-Key”: “Your Speedy API key”,
“X-RapidAPI-Host”: “api-football-v1.p.rapidapi.com”,
},
};
fetch(“https://api-football-v1.p.rapidapi.com/v3/nations”, countryOptions)
.then( (response) => response.json() )
.then( (response) => {
let countriesArray = { …response };
console.log(“International locations listing”, countriesArray.response);
setCountriesList(countriesArray.response);
})
.catch((err) => console.error(err));
}, []);
We’ve got a state variable to retailer the listing of nations. Subsequent, we’re going to import a part from the @wordpress/block-editor bundle known as InspectorControls which is the place the entire parts we have to create our settings controls are situated.
import { InspectorControls } from “@wordpress/block-editor”;
The bundle’s GitHub repo does a very good job explaining InspectorControls. In our instance, we will use it to regulate the API knowledge settings like Nation, League, and Season. Right here’s a preview so that you simply get an concept of the UI we’re making:
And as soon as these picks are made within the block settings, we use them in the block’s Edit perform:
<InspectorControls>
{ countriesList && (
<LeagueSettings
props={props}
countriesList={ countriesList }
setApiData={ setApiData }
></LeagueSettings>
)}
</InspectorControls>
Right here, I’m ensuring that we’re utilizing conditional rendering in order that the perform solely hundreds the part after the listing of nations is loaded. In the event you’re questioning about that LeagueSettings part, it’s a customized part I created in a separate parts subfolder within the block so we will have a cleaner and extra organized Edit perform as an alternative of tons of of traces of nation knowledge to take care of in a single file.
We are able to import it into the edit.js file like this:
import { LeagueSettings } from “./parts/LeagueSettings”;
Subsequent, we’re passing the required props to the LeagueSettings part from the mum or dad Edit part in order that we will entry the state variables and attributes from the LeagueSettings youngster part. We are able to additionally try this with different strategies just like the Context API to keep away from prop drilling, however what we now have proper now could be completely appropriate for what we’re doing.
The opposite elements of the Edit perform will also be transformed into parts. For instance, the league standings code will be put inside a separate part — like perhaps LeagueTable.js — after which imported similar to we imported LeagueSettings into the Edit perform.
Contained in the LeagueSettings.js file
LeagueSettings is rather like one other React part from which we will destructure the props from the mum or dad part. I’m going to make use of three state variables and an extra leagueID state as a result of we’re going to extract the ID from the league object:
const [country, setCountry] = useState(null);
const [league, setLeague] = useState(null);
const [season, setSeason] = useState(null);
const [leagueID, setLeagueID] = useState(null);
The very first thing we’re going to do is import the PanelBody part from the @wordpress/block-editor bundle:
import { PanelBody } from “@wordpress/block-editor”;
…and embody it in our return perform:
<PanelBody title=”Information settings” initialOpen={false}></PanelBody>
There are different panel tags and attributes — it’s simply my private choice to make use of these ones. Not one of the others are required… however take a look at all of the parts we now have accessible to make a settings panel! I just like the simplicity of the PanelBody for our use case. It expands and collapses to disclose the dropdown settings for the block and that’s it.
Talking of which, we now have a option to make for these picks. We might use the SelectControl part or a ComboBoxControl, which the docs describe as “an enhanced model of a SelectControl, with the addition of with the ability to seek for choices utilizing a search enter.” That’s good for us as a result of the listing of nations might get fairly lengthy and customers will have the ability to both do a search question or choose from an inventory.
Right here’s an instance of how a ComboboxControl might work for our nation listing:
<ComboboxControl
label=”Select nation”
worth={nation}
choices={ filteredCountryOptions }
onChange={ (worth) => handleCountryChange(worth) }
onInputChange={ (inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((choice) =>
choice.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
The ComboboxControl is configurable within the sense that we will apply completely different sizing for the management’s label and values:
{
worth: ‘small’,
label: ‘Small’,
},
However our API knowledge just isn’t on this syntax, so we will convert the countriesList array that comes from the mum or dad part when the block is included:
let setupCountrySelect;
setupCountrySelect = countriesList.map((nation) => {
return {
label: nation.title,
worth: nation.title,
};
});
When a rustic is chosen from the ComboboxControl, the nation worth modifications and we filter the info accordingly:
perform handleCountryChange(worth) {
// Set state of the nation
setCountry(worth);
// League code from RapidAPI
const choices = {
technique: “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?nation=${worth}`, choices)
.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 Nation choices
setupLeagueSelect = leagueOptions.map((league) => {
return {
label: league.league.title,
worth: league.league.title,
};
});
setFilteredLeagueOptions(setupLeagueSelect);
})
.catch((err) => console.error(err));
}
Word that I’m utilizing one other three state variables to deal with modifications when the nation choice modifications:
const [filteredCountryOptions, setFilteredCountryOptions] = useState(setupCountrySelect);
const [filteredLeagueOptions, setFilteredLeagueOptions] = useState(null);
const [filteredSeasonOptions, setFilteredSeasonOptions] = useState(null);
What concerning the different settings choices?
I’ll present the code that I used for the opposite settings however all it does is take regular instances into consideration whereas defining errors for particular instances. For instance, there will probably be errors in some nations and leagues as a result of:
there are not any standings for some leagues, andsome leagues have standings however they aren’t in a single desk.
This isn’t a JavaScript or React tutorial, so I’ll allow you to deal with the particular instances for the API that you simply plan to make use of:
perform handleLeagueChange(worth) {
setLeague(worth);
if (league) {
const selectedLeague = league.filter((el) => {
if (el.league.title === worth) {
return el;
}
});
if (selectedLeague) {
setLeague(selectedLeague[0].league.title);
setLeagueID(selectedLeague[0].league.id);
setupSeasonSelect = selectedLeague[0].seasons.map((season) => {
return {
label: season.12 months,
worth: season.12 months,
};
});
setFilteredSeasonOptions(setupSeasonSelect);
}
} else {
return;
}
}
perform handleSeasonChange(worth) {
setSeason(worth);
}
Submitting the settings picks
Within the final article, we made a button within the block editor that fetches recent knowledge from the API. There’s no extra want for it now that we now have settings. Nicely, we do want it — simply not the place it at present is. As a substitute of getting it instantly within the block that’s rendered within the block editor, we’re going to maneuver it to our PanelBody part to submit the settings picks.
So, again in LeagueSettings.js:
// When countriesList is loaded, present the nation combo field
{ countriesList && (
<ComboboxControl
label=”Select nation”
worth={nation}
choices={filteredCountryOptions}
onChange={(worth) => handleCountryChange(worth)}
onInputChange={(inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((choice) =>
choice.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
)}
// When filteredLeagueOptions is ready by means of handleCountryChange, present league combobox
{ filteredLeagueOptions && (
<ComboboxControl
label=”Select league”
worth={league}
choices={filteredLeagueOptions}
onChange={(worth) => handleLeagueChange(worth)}
onInputChange={(inputValue) => {
setFilteredLeagueOptions(
setupLeagueSelect.filter((choice) =>
choice.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
)}
// When filteredSeasonOptions is ready by means of handleLeagueChange, present season combobox
{ filteredSeasonOptions && (
<>
<ComboboxControl
label=”Select season”
worth={season}
choices={filteredSeasonOptions}
onChange={(worth) => handleSeasonChange(worth)}
onInputChange={
(inputValue) => {
setFilteredSeasonOptions(
setupSeasonSelect.filter((choice) =>
choice.label
.toLowerCase()
.startsWith(inputValue.toLowerCase()
)
);
}
}
/>
// When season is ready by means of handleSeasonChange, present the “Fetch knowledge” button
{
season && (
<button className=”fetch-data” onClick={() => getData()}>Fetch knowledge</button>
)
}
</>
</>
)}
Right here’s the outcome!
We’re in an excellent place with our block. We are able to render it within the block editor and the entrance finish of the location. We are able to fetch knowledge from an exterior API based mostly on a choice of settings we created that filters the info. It’s fairly darn useful!
However there’s one other factor we now have to sort out. Proper now, once we save the web page or publish that comprises the block, the settings we chosen for the block reset. In different phrases, these picks aren’t saved wherever. There’s slightly extra work to make these picks persistent. That’s the place we plan to go within the subsequent article, so keep tuned.
Making a Settings UI for a Customized WordPress Block initially printed on CSS-Methods, which is a part of the DigitalOcean household. You must get the e-newsletter.
Subscribe to MarketingSolution.
Receive web development discounts & web design tutorials.
Now! Lets GROW Together!