Building a Settings Panel for a Custom Block

Two earlier articles in this series covered fetching external API data for a custom Football Rankings block and rendering that data both on the front end and in the block editor. This article hooks into the block editor’s Settings panel — the sidebar that appears on the right when a block is selected — to give that block configurable options.

The block currently fetches a fixed set of rankings. That works, but it limits the block to one country, league, and season. The goal here is to let a user pick each of those values from controls inside the Settings panel, then fetch and display the matching standings.

What We Are Building

The external API’s data is organized under a few top-level endpoints. Seasons and countries both point to a leagues endpoint, which in turn provides the standings data the block already uses. To populate the rankings table for a specific country and season, we first have to resolve which league identifiers are available.

For this block, the Settings panel will contain three controls:

  • Choose Country
  • Choose League
  • Choose Season

Those selections are then submitted via a button in the same panel, which triggers the API request that renders the appropriate rankings table.

Loading the Country List

The first step is to fetch the list of countries from the API when the block is placed into a post or page. This avoids making requests when the block isn’t in use. The logic is similar to the fetch-and-store approach used in the earlier front-end article, but with a different endpoint and a separate block attribute to store the returned list.

One way to make this easier is to fetch the countries the moment the block is inserted into the editor. The response is held in a state variable inside the block’s Edit function, ready to be passed to the settings components.

The next piece is bringing in InspectorControls from the @wordpress/block-editor package. This is the wrapper component that places our custom controls into the block editor’s Settings panel.

The block uses conditional rendering so that the settings component only mounts once the country list has loaded. This prevents empty dropdowns and keeps the UI from showing unavailable options.

Organizing the Settings Component

Rather than crowding the Edit function with hundreds of lines of control code, the settings UI lives in its own component called LeagueSettings, stored in a components subfolder inside the block directory. The Edit function imports it and passes the needed props: the countries list, the block attributes, and the state setters.

Prop drilling is acceptable here — the component hierarchy is shallow enough that reaching for the Context API would be overkill for this use case.

Other parts of the Edit function could be split into separate components as well, such as moving the league standings rendering into a dedicated LeagueTable.js file.

Inside LeagueSettings

LeagueSettings works like any React component — it destructures the props passed from Edit. A few state variables track the selected country, league, and season, plus a leagueID state that extracts the ID from the chosen league object.

For the panel itself, the PanelBody component from @wordpress/block-editor provides an expandable/collapsible container. Several panel-related components exist, but PanelBody alone is sufficient to hold the block’s dropdown settings.

Choosing the Input Controls

WordPress ships two relevant selection components. The SelectControl renders a standard dropdown. The ComboBoxControl is an enhanced version that also allows searching through the options via a text input. That is useful here, since the list of countries can get long.

The ComboboxControl accepts an array of objects with value and label properties. Since the API returns a different shape for each country, the code maps the API’s country list into that expected format before passing it to the control.

When a country is selected, the component updates its state and filters the available leagues accordingly, resetting related states — such as the current league selection and its ID — to their default values.

Handling the Other Selections

The league and season controls follow the same pattern as the country control. Special cases exist, though. Some leagues have no standings at all, while others produce standings that are not presented in a single table. The source code for these selections accounts for those normal cases and defines explicit error handling for the edge cases:

  • No standings available for certain leagues.
  • Standings split across multiple tables for others.

Since API responses vary widely, adjusting the special-case handling for a different API service is expected.

Moving the Fetch Button

The previous article placed a fetch button directly inside the block’s rendered content in the editor. With settings in place, that button moves into the PanelBody component. Clicking it now reads the country, league, and season values selected in the settings panel and triggers the appropriate API call.

With that arrangement, the block displays the Settings panel in the editor sidebar, the submit button inside the panel, and the resulting rankings table rendered from the returned data.

What Still Remains

The block now fetches external data and lets users filter it through the editor’s Settings panel. That said, the selections aren’t yet persisted — saving the post or page does not currently retain the chosen country, league, or season. Making those settings persistent is the next step in this series.