В процессе работы над компонентом нужно разделить опции выпадающего списка на группы. Я писал ранее как это сделать просто в коде тут: статья, пост. Но как сделать такой список для использования в описаниях форм в xml?
Первой мыслью было сделать свой тип поля, расширяющий стандартный \Joomla\CMS\Form\Field\ListField
. Однако, в ядре Joomla нашёлся уже готовый класс поля для группированных списков \Joomla\CMS\Form\Field\GroupedlistField
. Он расширяет напрямую FormField
и имеет 2 метода - getGroups()
и getInput()
.
В getInput()
вызывается метод getGroups()
для получения массивов с группами опций и его можно было спокойно заменить на collectLayoutData()
, где этой работе самое и место, но это не слишком принципиально. И там и там работа делается. Поэтому нас интересует именно метод getGroups()
.
Мы создаём свой класс поля, расширяем GroupedlistField
. Делаем обязательно свой $type
для поля и реализуем метод getGroups()
. Всё.
<?php
use Joomla\CMS\Form\Field\GroupedlistField;
use Joomla\CMS\HTML\HTMLHelper;
class ServerschemelistField extends GroupedlistField
{
// type совпадает с именем файла и класса
// без суффикса 'Field'
protected $type = 'Serverschemelist';
/**
* Method to get the field options.
*
* @return array The field option objects.
*
* @throws Exception
*
* @since 1.0.0
*/
protected function getGroups(): array
{
// наши группы
$group1 = [];
$group2 = [];
$data = []; // какой-то массив с чем-нибудь
// Собираем первую группу опций
foreach ($data as $item) {
$optionattr = [];
// Атрибуты для <option>
if ($something_happend) {
$optionattr['option.attr'] = [
'selected' => 'selected',
'onclick' => 'earthQuake()',
'showon' => 'field1:value1000',
];
}
$group1[] = HTMLHelper::_(
'select.option',
$item->option_value,
$item->option_label_text,
$optionattr
);
}
// Аналогично собираем $group2
// ...
$groups = [
['Имя группы 1'] = $group1,
['Имя группы 2'] = $group2,
];
// В parent::getGroups() будут значения
// из xml-описания формы, если они есть.
// Соединяем их с нашими.
return array_merge(parent::getGroups(), $groups);
}
}