为自定义 WordPress 块创建设置 UI PlatoBlockchain 数据智能。 垂直搜索。 人工智能。

为自定义 WordPress 块创建设置 UI

到目前为止,我们已经介绍了如何在自定义 WordPress 块中处理来自外部 API 的数据。 我们经历了以下过程 获取该数据以供前端使用 一个 WordPress 网站,以及如何 直接在 WordPress 块编辑器中呈现 将块放在内容中时。 这一次,我们将连接到块编辑器的控制面板,为我们制作的块创建一个设置 UI,从而连接这两篇文章。

在 WordPress 块中使用外部 API

你知道我指的是控制面板,对吧? 右侧的面板包含块编辑器中的帖子和块设置。

为自定义 WordPress 块创建设置 UI

看到红色突出显示的区域了吗? 那是控制面板。 当前选择了一个段落块,其设置显示在面板中。 我们可以更改样式、颜色、版式……很多东西!

好吧,这正是我们这次要做的。 我们将为我们在上两篇文章中处理的 Football Rankings 块的设置创建控件。 上次,我们在块中制作了一个按钮,用于获取足球排名的外部数据。 我们已经知道我们需要的 URL 和端点。 但是如果我们想获取不同国家的排名怎么办? 或者也许是不同的联赛? 不同季节的数据如何?

我们需要表单控件来做到这一点。 我们可以使用交互式 React 组件——比如 反应选择 — 浏览可用于解析该数据的各种 API 选项。 但是没有必要这样做,因为 WordPress 附带了一堆我们可以直接挂接的核心组件!

文件 对于这些组件 - 称为 InspectorControls - 越来越好 WordPress 块编辑器手册. 随着时间的推移,情况会变得更好,但与此同时,我们也有 WordPress 古腾堡故事书WordPress 古腾堡组件 网站以获得更多帮助。

API架构

在我们连接到任何东西之前,最好先弄清楚我们需要什么。 我已经绘制出我们正在获取的 RapidAPI 数据的结构,因此我们知道我们可以使用什么:

为获取的自定义 WordPress 块数据连接 API 端点的流程图。
信用: API-足球

赛季和国家/地区是映射到联赛端点的两个顶级端点。 从那里,我们得到了我们已经用来填充排名表的其余数据。 因此,我们要做的是在 WordPress 块编辑器中创建设置,按季节、国家和联赛过滤数据,然后将过滤后的数据传递到排名表中。 这使我们能够在任何 WordPress 页面中放置块,或在块中发布和显示数据的变体。

要想拿到积分榜,首先要拿到联赛。 为了获得联赛,我们首先需要获得国家和/或赛季。 您可以在 RapidAPI 仪表板中查看各种端点。

显示 API 数据的 Rapid API 仪表板的全屏。
为自定义 WordPress 块创建设置 UI

我们可以使用不同的数据组合来填充排名,您可能对所需的数据有偏好。 在本文中,我们将在块设置面板中创建以下选项:

  • 选择国家
  • 选择联赛
  • 选择季节

然后我们将有一个按钮来提交这些选择并获取相关数据并将它们传递到排名表中。

加载并存储国家列表

如果我们没有可供选择的国家/地区列表,我们将无法选择我们想要哪个国家/地区的数据。 因此,我们的首要任务是从 RapidAPI 中获取国家列表。

理想的做法是在块实际用于页面或发布内容时获取国家列表。 如果该块未在使用中,则无需获取任何内容。 该方法与我们在 第一篇,不同之处在于我们使用不同的 API 端点和不同的属性来存储返回国家/地区的列表。 还有其他 WordPress 方法来获取数据,比如 api 获取,但这超出了我们在这里所做的范围。

我们可以在从 API 数据复制后手动包含国家/地区列表,也可以使用单独的 API 或库来填充国家/地区。 但是我们使用的 API 已经有一个国家列表,所以我只使用它的一个端点。 让我们确保在将块插入页面或在块编辑器中发布内容时加载初始国家/地区列表:

// 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));
}, []);

我们有一个状态变量来存储国家列表。 接下来,我们将从中导入一个组件 @wordpress/块编辑器 包称为 InspectorControls 这是我们创建设置控件所需的所有组件所在的位置。

import { InspectorControls } from "@wordpress/block-editor";

包裹的 GitHub回购 解释得很好 InspectorControls. 在我们的示例中,我们可以使用它来控制国家、联赛和赛季等 API 数据设置。 这是一个预览,以便您了解我们正在制作的 UI:

WordPress 块的自定义设置 UI,显示自定义块的三个设置选项和一个用于获取数据的蓝色按钮。
为自定义 WordPress 块创建设置 UI

一旦在块设置中做出这些选择,我们就可以在 街区的 Edit 功能:


  { countriesList && (
    
  )}

在这里,我确保我们正在使用条件渲染,以便该函数仅加载组件 after 国家列表已加载。 如果你想知道 LeagueSettings 组件,它是我在一个单独的 components 块中的子文件夹,这样我们就可以有一个更干净,更有条理的 Edit 函数,而不是在单个文件中处理数百行国家/地区数据。

显示当前文件的块目录的文件结构。
为自定义 WordPress 块创建设置 UI

我们可以将其导入 edit.js 像这样的文件:

import { LeagueSettings } from "./components/LeagueSettings";

接下来,我们将所需的道具传递给 LeagueSettings 来自父级的组件 Edit 组件,以便我们可以访问状态变量和属性 LeagueSettings 子组件。 我们也可以用其他方法来做到这一点,比如 上下文API 以避免螺旋桨钻探,但我们现在拥有的非常适合我们正在做的事情。

的其他部分 Edit 功能也可以转换为组件。 例如,联赛排名代码可以放在一个单独的组件中——比如 LeagueTable.js — 然后像我们导入的那样导入 LeagueSettingsEdit 功能。

里面的 LeagueSettings.js 文件

LeagueSettings 就像另一个 反应组件 从中我们可以从父组件中解构道具。 我将使用三个状态变量和一个额外的 leagueID 状态,因为我们要从中提取 ID league 宾语:

const [country, setCountry] = useState(null);
const [league, setLeague] = useState(null);
const [season, setSeason] = useState(null);
const [leagueID, setLeagueID] = useState(null);

我们要做的第一件事是导入 PanelBody @wordpress/block-editor 包中的组件:

import { PanelBody } from "@wordpress/block-editor";

...并将其包含在我们的 return 功能:

这里有 其他面板标签和属性 - 使用这些只是我个人的偏好。 其他的都不是必需的……但是 查看所有组件 我们可以制作一个设置面板! 我喜欢它的简单 PanelBody 对于我们的用例。 它会展开和折叠以显示块的下拉设置,仅此而已。

说到这一点,我们可以为这些选择做出选择。 我们可以使用 SelectControl 组件或 ComboBoxControl,文档将其描述为“增强版的 SelectControl,此外还能够使用搜索输入来搜索选项。” 这对我们来说很好,因为国家列表可能会变得很长,用户将能够进行搜索查询或从列表中进行选择。

这是一个如何 ComboboxControl 可以为我们的国家列表工作:

 handleCountryChange(value) }
  onInputChange={ (inputValue) => {
    setFilteredCountryOptions(
      setupCountrySelect.filter((option) =>
        option.label
          .toLowerCase()
          .startsWith(inputValue.toLowerCase())
      )
    );
  }}
/>

ComboboxControl 在我们可以为控件的标签和值应用不同大小的意义上是可配置的:

{
  value: 'small',
  label: 'Small',
},

但是我们的 API 数据不在这种语法中,所以我们可以将 countriesList 包含块时来自父组件的数组:

let setupCountrySelect;

setupCountrySelect = countriesList.map((country) => {
  return {
    label: country.name,
    value: country.name,
  };
});

当从中选择一个国家时 ComboboxControl,国家价值发生变化,我们相应地过滤数据:

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));
}

请注意,当国家选择发生变化时,我使用另外三个状态变量来处理变化:

const [filteredCountryOptions, setFilteredCountryOptions] = useState(setupCountrySelect);
const [filteredLeagueOptions, setFilteredLeagueOptions] = useState(null);
const [filteredSeasonOptions, setFilteredSeasonOptions] = useState(null);

其他设置选项呢?

我将展示我用于其他设置的代码,但它所做的只是在为特殊情况定义错误时考虑正常情况。 例如,在某些国家和联赛中会出现错误,因为:

  • 有些联赛没有积分榜,并且
  • 一些联赛有排名,但它们不在一张表中。

这不是 JavaScript 或 React 教程,因此我会让您处理您计划使用的 API 的特殊情况:

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);
}

提交设置选择

上篇文章,我们在块编辑器中制作了一个按钮,用于从 API 获取新数据。 既然我们有了设置,就不再需要它了。 好吧,我们确实需要它——只是不在目前的位置。 我们不会将它直接放在块编辑器中呈现的块中,而是将其移动到我们的 PanelBody 组件提交设置选择。

所以,回到 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 && (
        
      )
    }
    
  
)}

这是结果!

我们的街区处于一个非常好的位置。 我们可以在块编辑器和网站前端渲染它。 我们可以根据我们创建的过滤数据的设置选择从外部 API 获取数据。 它非常实用!

但还有一件事我们必须解决。 现在,当我们保存包含该块的页面或帖子时,我们为块重置选择的设置。 换句话说,这些选择不会保存在任何地方。 要使这些选择持久化,还有一些工作要做。 这就是我们计划在下一篇文章中介绍的地方,敬请期待。

时间戳记:

更多来自 CSS技巧