Поки що ми розглянули, як працювати з даними із зовнішнього API у спеціальному блоці WordPress. Ми пройшли через процес отримання цих даних для використання на інтерфейсі сайту WordPress і як це зробити візуалізувати його безпосередньо в редакторі блоків WordPress при розміщенні блоку в контенті. Цього разу ми збираємося поєднати ці дві статті, підключившись до панелі керування редактора блоків, щоб створити інтерфейс налаштування для створеного нами блоку.
Робота із зовнішніми API у блоках WordPress
Ви знаєте панель керування, про яку я маю на увазі, чи не так? Це та панель праворуч, яка містить налаштування публікацій і блокувань у редакторі блоків.
Бачите виділену червоним область? Це панель керування. Наразі вибрано блок «Абзац», а його параметри відображаються на панелі. Ми можемо змінювати стилі, колір, типографіку… багато речей!
Що ж, саме це ми робимо цього разу. Ми збираємося створити елементи керування для налаштувань блоку Football Rankings, над якими ми працювали в останніх двох статтях. Минулого разу ми зробили в нашому блоці кнопку, яка отримує зовнішні дані для футбольного рейтингу. Ми вже знали URL-адресу та кінцеві точки, які нам потрібні. Але що, якщо ми хочемо отримати рейтинг для іншої країни? А може, інша ліга? Як щодо даних іншого сезону?
Для цього нам потрібні елементи керування формою. Ми могли б використовувати інтерактивні компоненти React, наприклад React-Select — для перегляду різних параметрів API, які доступні для аналізу цих даних. Але в цьому немає потреби, оскільки WordPress постачається з купою основних компонентів, які ми підключаємо безпосередньо!
Команда документація для цих компонентів — наз InspectorControls
— стає краще в Посібник з редактора блоків WordPress. З часом це стане ще краще, але тим часом ми також маємо Книга оповідань Гутенберга WordPress та Компоненти WordPress Gutenberg сайти для додаткової допомоги.
Архітектура API
Перш ніж приступати до будь-чого, було б гарною ідеєю визначити, що саме нам потрібно в першу чергу. Я визначив структуру даних RapidAPI, які ми отримуємо, щоб ми знали, що нам доступно:
Сезони та країни — це дві кінцеві точки верхнього рівня, які відображаються на кінцеву точку ліг. Звідти ми маємо решту даних, які вже використовуємо для заповнення таблиці рейтингів. Отже, ми хочемо створити налаштування в редакторі блоків WordPress, які фільтрують дані за сезоном, країною та лігою, а потім передадуть відфільтровані дані в таблицю рейтингу. Це дає нам можливість видаляти блок на будь-якій сторінці або публікації WordPress і відображати варіанти даних у блоці.
Щоб отримати турнірну таблицю, нам потрібно спочатку отримати ліги. І щоб отримати ліги, нам спочатку потрібно отримати країни та/або сезони. Ви можете переглянути різні кінцеві точки на інформаційній панелі RapidAPI.
Існують різні комбінації даних, які ми можемо використовувати для заповнення рейтингу, і ви можете вибрати, які дані вам потрібні. Для цієї статті ми збираємося створити такі параметри на панелі налаштувань блоку:
- Виберіть країну
- Виберіть Лігу
- Виберіть Сезон
Тоді ми матимемо кнопку, щоб надіслати ці вибрані дані, отримати відповідні дані та передати їх у таблицю рейтингу.
Завантажте та збережіть список країн
Ми не можемо вибрати країну, для якої нам потрібні дані, якщо у нас немає списку країн для вибору. Отже, наше перше завдання — отримати список країн із 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, такими як країна, ліга та сезон. Ось попередній перегляд, щоб ви мали уявлення про інтерфейс користувача, який ми створюємо:
І коли ці вибори зроблені в налаштуваннях блоку, ми використовуємо їх блоку Edit
функція:
{ countriesList && (
)}
Тут я переконався, що ми використовуємо умовний рендеринг, щоб функція завантажувала лише компонент після завантажується список країн. Якщо вам це цікаво LeagueSettings
це спеціальний компонент, який я створив окремо components
підпапку в блоці, щоб ми могли мати чистіші та більш організовані Edit
замість сотень рядків даних про країну в одному файлі.
Ми можемо імпортувати його в 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
компонент або a ComboBoxControl
, який у документах описано як «розширена версія a SelectControl
, з додаванням можливості пошуку параметрів за допомогою пошукового введення». Це приємно для нас, тому що список країн може бути досить довгим, і користувачі зможуть або виконати пошуковий запит, або вибрати зі списку.
Ось приклад того, як a 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 на основі створених нами налаштувань, які фільтрують дані. Це до біса функціонально!
Але є ще одна річ, з якою ми повинні впоратися. Прямо зараз, коли ми зберігаємо сторінку чи публікацію, яка містить блокування, налаштування, які ми вибрали для блокування, скидаються. Іншими словами, ці виділення ніде не зберігаються. Треба ще трохи попрацювати, щоб зробити цей вибір постійним. Саме про це ми плануємо поговорити в наступній статті, тому слідкуйте за оновленнями.