Создание пользовательского интерфейса настроек для пользовательского блока WordPress PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

Создание пользовательского интерфейса настроек для пользовательского блока WordPress

До сих пор мы рассмотрели, как работать с данными из внешнего API в пользовательском блоке WordPress. Мы прошли через процесс извлечение этих данных для использования во внешнем интерфейсе сайта WordPress и как отображать его непосредственно в редакторе блоков WordPress при размещении блока в контенте. На этот раз мы собираемся соединить эти две статьи, подключившись к панели управления редактора блоков, чтобы создать пользовательский интерфейс настроек для созданного нами блока.

Работа с внешними API в блоках WordPress

Вы знаете панель управления, о которой я говорю, верно? Это панель справа, которая содержит настройки постов и блоков в редакторе блоков.

Создание пользовательского интерфейса настроек для пользовательского блока WordPress

Видите ту область, выделенную красным? Это панель управления. В настоящее время выбран блок «Абзац», и его настройки отображаются на панели. Мы можем изменить стили, цвет, типографику… многое другое!

Ну, это именно то, что мы делаем на этот раз. Мы собираемся создать элементы управления для настроек блока Football Rankings, над которым мы работали в последних двух статьях. В прошлый раз мы сделали в нашем блоке кнопку, которая извлекает внешние данные для футбольного рейтинга. Мы уже знали URL-адрес и конечные точки, которые нам нужны. Но что, если мы хотим получить рейтинг для другой страны? Или, может быть, другая лига? Как насчет данных из другого сезона?

Для этого нам нужны элементы управления формой. Мы могли бы использовать интерактивные компоненты React, например Реагировать-выбрать — для просмотра различных параметров API, доступных для анализа этих данных. Но в этом нет необходимости, так как WordPress поставляется с набором основных компонентов, к которым мы подключаемся прямо сейчас!

Ассоциация документации для этих компонентов — называется InspectorControls - становится лучше в Справочник редактора блоков WordPress. Со временем это станет еще лучше, но пока у нас также есть Сборник рассказов WordPress Гутенберг и Компоненты WordPress Гутенберг сайты для получения дополнительной помощи.

Архитектура API

Прежде чем мы что-то зацепим, было бы неплохо наметить, что нам нужно в первую очередь. Я наметил структуру данных RapidAPI, которые мы извлекаем, чтобы мы знали, что нам доступно:

Блок-схема, соединяющая конечные точки API для настраиваемых данных блока WordPress, которые извлекаются.
Кредит: API-футбол

Сезоны и страны — это две конечные точки верхнего уровня, которые сопоставляются с конечной точкой лиг. Оттуда у нас есть остальные данные, которые мы уже используем для заполнения таблицы ранжирования. Итак, что мы хотим сделать, так это создать настройки в редакторе блоков WordPress, которые будут фильтровать данные по сезону, стране и лиге, а затем передавать отфильтрованные данные в таблицу рейтинга. Это дает нам возможность размещать блок на любой странице или публикации WordPress и отображать варианты данных в блоке.

Чтобы получить турнирную таблицу, нам нужно сначала получить лиги. И чтобы получить лиги, нам сначала нужно получить страны и/или сезоны. Вы можете просмотреть различные конечные точки на панели управления RapidAPI.

Полноэкранный режим для панели управления Rapid API, которая визуализирует данные API.
Создание пользовательского интерфейса настроек для пользовательского блока WordPress

Существуют различные комбинации данных, которые мы можем использовать для заполнения рейтинга, и у вас могут быть предпочтения в отношении того, какие данные вам нужны. Ради этой статьи мы собираемся создать следующие параметры в панели настроек блока:

  • Выберите страну
  • Выберите лигу
  • Выберите сезон

Затем у нас будет кнопка для отправки этих выборов и получения соответствующих данных и передачи их в таблицу рейтингов.

Загрузить и сохранить список стран

Мы не можем выбрать, по какой стране нам нужны данные, если у нас нет списка стран для выбора. Итак, наша первая задача — получить список стран из 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, такими как страна, лига и сезон. Вот предварительный просмотр, чтобы вы получили представление о пользовательском интерфейсе, который мы делаем:

Пользовательский интерфейс пользовательских настроек для блока WordPress, показывающий три параметра настроек для пользовательского блока и синюю кнопку для получения данных.
Создание пользовательского интерфейса настроек для пользовательского блока WordPress

И как только эти выборки сделаны в настройках блока, мы используем их в блок Edit функция:


  { countriesList && (
    
  )}

Здесь я удостоверяюсь, что мы используем условный рендеринг, чтобы функция загружала только компонент после список стран загружен. Если вам интересно об этом LeagueSettings компонент, это пользовательский компонент, который я создал в отдельном components подпапка в блоке, чтобы мы могли иметь более чистый и организованный Edit функцию вместо сотен строк данных о стране, которые нужно обрабатывать в одном файле.

Структура файла для каталога блока, показывающего текущий файл.
Создание пользовательского интерфейса настроек для пользовательского блока WordPress

Мы можем импортировать его в edit.js файл вроде этого:

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

Затем мы передаем необходимые реквизиты в LeagueSettings компонент от родителя Edit компонент, чтобы мы могли получить доступ к переменным состояния и атрибутам из LeagueSettings дочерний компонент. Мы также можем сделать это с помощью других методов, таких как Контекстный API чтобы избежать сверления опор, но то, что у нас есть прямо сейчас, идеально подходит для того, что мы делаем.

Остальные части Edit функция также может быть преобразована в компоненты. Например, код турнирной таблицы лиги можно поместить в отдельный компонент — например, возможно LeagueTable.js — а затем импортировать так же, как мы импортировали LeagueSettings в Edit функции.

Внутри LeagueSettings.js файл

LeagueSettings точно так же, как другой Компонент React из которого мы можем деструктурировать реквизит из родительского компонента. Я собираюсь использовать три переменные состояния и дополнительную leagueID состояние, потому что мы собираемся извлечь идентификатор из 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 хитрости