Провайдеры данных в ui.entity-selector
Провайдер данных — PHP-класс, который загружает элементы для Dialog с сервера. Провайдер нужен, когда список нельзя передать локально в items: данные зависят от прав пользователя, поисковой строки, выбранного контекста или внешнего хранилища.
Провайдер может заполнить диалог элементами и вкладками, выполнить поиск, вернуть заранее выбранные элементы и загрузить дочерние элементы древовидной структуры.
Для пользователей, отделов, проектов, чатов и чат-ботов провайдер уже зарегистрирован в Bitrix Framework. Эти типы объектов описаны в статье Стандартные провайдеры. Собственный провайдер нужен для типа объекта, которого нет среди стандартных.
Зарегистрировать тип объекта
Добавьте тип объекта в настройки модуля в ключ ui.entity-selector.
PHP-файл конфигурации модуля возвращает настройки, которые Bitrix Framework читает при регистрации модуля. В примере показан только фрагмент массива с настройкой ui.entity-selector.
<?php
return [
'ui.entity-selector' => [
'value' => [
'entities' => [
[
'entityId' => 'project',
'provider' => [
'moduleId' => 'my.module',
'className' => \My\Module\Integration\UI\EntitySelector\ProjectProvider::class,
],
],
],
'extensions' => [
'my.module.entity-selector',
],
],
'readonly' => true,
],
];
entityId должен совпадать с id в JavaScript-массиве entities. По этому значению серверная часть находит провайдер.
extensions подключает JavaScript-расширения, в которых можно определить глобальные настройки типа объекта, классы футеров, заголовков или заглушек.
| Путь в настройках | Тип | Обязательный | Назначение |
|---|---|---|---|
ui.entity-selector.value.entities[].entityId |
string |
да | Идентификатор типа объекта для серверного поиска провайдера |
ui.entity-selector.value.entities[].provider.moduleId |
string |
да | Модуль, в котором находится класс провайдера |
ui.entity-selector.value.entities[].provider.className |
string |
да | Полное имя PHP-класса провайдера |
ui.entity-selector.value.extensions |
string[] |
нет | JavaScript-расширения с глобальными настройками типа объекта |
ui.entity-selector.readonly |
boolean |
нет | Защищает настройку от изменения после регистрации |
Задать глобальные настройки типа объекта
Глобальные настройки типа объекта задаются в config.php JavaScript-расширения. В settings.entities передайте массив настроек.
Ключи dynamicLoad, dynamicSearch и остальные параметры типа объекта передавайте внутри options. JavaScript-часть расширения читает только id и options этого элемента массива, остальные соседние ключи она игнорирует.
<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true)
{
die();
}
return [
'settings' => [
'entities' => [
[
'id' => 'project',
'options' => [
'dynamicLoad' => true,
'dynamicSearch' => true,
'searchFields' => [
[
'name' => 'code',
'type' => 'string',
],
],
'itemOptions' => [
'default' => [
'avatar' => '/local/images/project.svg',
'link' => '/projects/#id#/',
],
],
'tagOptions' => [
'default' => [
'textColor' => '#1066bb',
'bgColor' => '#bcedfc',
],
],
],
],
],
],
];
Глобальные настройки применяются к типу объекта во всех диалогах. Локальные настройки из entities при создании Dialog уточняют сценарий конкретной формы.
Настроить фильтры типа объекта
Фильтр — PHP-класс, который наследует Bitrix\UI\EntitySelector\BaseFilter и изменяет набор элементов после загрузки провайдером. Используйте фильтр, когда один и тот же тип объекта нужно ограничивать по дополнительным правилам конкретного сценария.
Зарегистрируйте фильтр в настройках модуля. entityId должен совпадать с типом объекта, к которому применяется фильтр. id фильтра передается в JavaScript-настройках entities[].filters.
<?php
return [
'ui.entity-selector' => [
'value' => [
'filters' => [
[
'entityId' => 'user',
'id' => 'my.module.activeUsers',
'className' => \My\Module\Integration\UI\EntitySelector\ActiveUsersFilter::class,
],
],
],
'readonly' => true,
],
];
const dialog = new Dialog({
targetNode: button,
entities: [
{
id: 'user',
filters: [
{
id: 'my.module.activeUsers',
options: {
departmentId: 15,
},
},
],
},
],
});
Класс фильтра должен реализовать isAvailable() и apply(array $items, Dialog $dialog). В apply() передается массив элементов текущего типа объекта, которые уже добавлены в диалог.
<?php
namespace My\Module\Integration\UI\EntitySelector;
use Bitrix\UI\EntitySelector\BaseFilter;
use Bitrix\UI\EntitySelector\Dialog;
final class ActiveUsersFilter extends BaseFilter
{
public function isAvailable(): bool
{
return true;
}
public function apply(array $items, Dialog $dialog): void
{
foreach ($items as $item)
{
if ($item->getCustomData()->get('active') !== true)
{
$item->setHidden();
}
}
}
}
Создать провайдер
Класс провайдера наследуется от Bitrix\UI\EntitySelector\BaseProvider. Минимально он должен реализовать isAvailable() и getItems().
<?php
namespace My\Module\Integration\UI\EntitySelector;
use Bitrix\UI\EntitySelector\BaseProvider;
use Bitrix\UI\EntitySelector\Dialog;
use Bitrix\UI\EntitySelector\Item;
use Bitrix\UI\EntitySelector\SearchQuery;
use Bitrix\UI\EntitySelector\Tab;
final class ProjectProvider extends BaseProvider
{
private const ITEMS = [
1 => 'Проект внедрения',
2 => 'Поддержка сайта',
];
private array $options = [];
public function __construct(array $options = [])
{
parent::__construct();
$this->options = $options;
}
public function isAvailable(): bool
{
return true;
}
public function getItems(array $ids): array
{
$items = [];
foreach ($ids as $id)
{
if (!isset(self::ITEMS[$id]))
{
continue;
}
$items[] = new Item([
'id' => $id,
'entityId' => 'project',
'title' => self::ITEMS[$id],
'tabs' => 'projects',
]);
}
return $items;
}
public function fillDialog(Dialog $dialog): void
{
$dialog->addTab(new Tab([
'id' => 'projects',
'title' => 'Проекты',
]));
foreach (self::ITEMS as $id => $title)
{
$dialog->addItem(new Item([
'id' => $id,
'entityId' => 'project',
'title' => $title,
'tabs' => 'projects',
]));
}
}
public function doSearch(SearchQuery $searchQuery, Dialog $dialog): void
{
$query = mb_strtolower($searchQuery->getQuery());
foreach (self::ITEMS as $id => $title)
{
if ($query !== '' && mb_strpos(mb_strtolower($title), $query) === false)
{
continue;
}
$dialog->addItem(new Item([
'id' => $id,
'entityId' => 'project',
'title' => $title,
'tabs' => 'projects',
]));
}
}
}
isAvailable() должен учитывать права текущего пользователя. Если метод вернет false, серверная часть не использует провайдер.
Как JavaScript связан с PHP
Серверная часть не вызывает все методы провайдера сразу. Нужный метод зависит от настроек, которые переданы в Dialog, и от действия пользователя в интерфейсе.
| JavaScript-настройка | PHP API | Что происходит |
|---|---|---|
entities[].dynamicLoad |
BaseProvider::fillDialog(Dialog $dialog) |
Провайдер заполняет диалог элементами и вкладками при загрузке |
entities[].dynamicSearch |
BaseProvider::doSearch(SearchQuery $searchQuery, Dialog $dialog) |
Провайдер добавляет найденные элементы в серверное представление диалога |
preselectedItems |
BaseProvider::getPreselectedItems(array $ids) |
Провайдер возвращает данные заранее выбранных элементов по идентификаторам |
| Динамические дочерние элементы | BaseProvider::getChildren(Item $parentItem, Dialog $dialog) |
Провайдер добавляет дочерние элементы для узла дерева |
Недавние элементы и context |
Dialog::getRecentItems(), Dialog::getGlobalRecentItems() |
Провайдер получает локальную и глобальную историю выбора пользователя |
Методы BaseProvider
| Метод | Что делает |
|---|---|
isAvailable() |
Возвращает true, если провайдер доступен текущему пользователю и сценарию |
getItems(array $ids) |
Возвращает массив Item для переданных идентификаторов |
getPreselectedItems(array $ids) |
Возвращает заранее выбранные элементы |
getOptions() |
Возвращает параметры провайдера |
getOption(string $option, $defaultValue = null) |
Возвращает один параметр провайдера или значение по умолчанию |
fillDialog(Dialog $dialog) |
Добавляет вкладки и элементы в диалог при загрузке |
getChildren(Item $parentItem, Dialog $dialog) |
Добавляет дочерние элементы для древовидных типов объектов |
doSearch(SearchQuery $searchQuery, Dialog $dialog) |
Добавляет найденные элементы при серверном поиске |
handleBeforeItemSave(Item $item) |
Изменяет элемент перед сохранением в недавних |
getPreselectedItems() возвращает элементы, которые уже сохранены в форме и должны отображаться как выбранные.
Метод используют, когда сохраненное значение нужно показать в интерфейсе, но элемент не должен попадать в обычный список выбора. Например, при редактировании записи можно показать ранее выбранного уволенного сотрудника и не показывать его во вкладке недавних элементов или в структуре компании.
Если в вашем типе объекта нет разной видимости для выбора и для уже сохраненных значений, getPreselectedItems() может возвращать те же элементы, что и getItems().
public function getPreselectedItems(array $ids): array
{
return $this->loadUsers($ids, [
'includeInactive' => true,
]);
}
public function getItems(array $ids): array
{
return $this->loadUsers($ids, [
'activeOnly' => true,
]);
}
SearchQuery
SearchQuery содержит поисковую строку, разобранные слова запроса и флаг кеширования. Диалог создает объект и передает его в doSearch(SearchQuery $searchQuery, Dialog $dialog).
| Метод | Что делает |
|---|---|
getQuery() |
Возвращает нормализованную поисковую строку |
getRawQuery() |
Возвращает исходную поисковую строку |
getQueryWords() |
Возвращает слова поискового запроса |
isCacheable() |
Возвращает true, если ответ можно кешировать |
setCacheable(bool $flag = true) |
Разрешает или запрещает кеширование текущего ответа |
PHP Dialog
Bitrix\UI\EntitySelector\Dialog — серверное представление диалога. Провайдер получает объект в методах fillDialog(), doSearch() и getChildren() и добавляет в него элементы, вкладки, ошибки, заголовок или футер.
| Метод | Что делает |
|---|---|
getId() |
Возвращает идентификатор диалога |
getContext() |
Возвращает контекст недавних элементов |
getCurrentUserId() |
Возвращает идентификатор текущего пользователя |
addItem(Item $item) |
Добавляет один элемент в диалог |
addItems(array $items) |
Добавляет массив элементов в диалог |
getItemCollection() |
Возвращает коллекцию элементов диалога |
addRecentItem(Item $item) |
Добавляет один элемент на вкладку недавних элементов |
addRecentItems(array $items) |
Добавляет массив элементов на вкладку недавних элементов |
getRecentItems() |
Возвращает недавние элементы текущего context |
getGlobalRecentItems() |
Возвращает недавние элементы из других контекстов |
cleanRecentItems() |
Очищает коллекцию недавних элементов диалога |
setHeader(string $header, array $options = []) |
Задает заголовок диалога |
getHeader() |
Возвращает заголовок диалога |
setFooter(string $footer, array $options = []) |
Задает футер диалога |
getFooter() |
Возвращает футер диалога |
addTab(Tab $tab) |
Добавляет вкладку в диалог |
getTabs() |
Возвращает вкладки диалога |
getTab(string $tabId) |
Возвращает вкладку по идентификатору |
addEntity(Entity $entity) |
Добавляет тип объекта в диалог |
getEntities() |
Возвращает типы объектов диалога |
getEntity(string $entityId) |
Возвращает тип объекта по идентификатору |
setCustomData(array $customData) |
Задает дополнительные данные сценария |
getCustomData() |
Возвращает дополнительные данные сценария |
load() |
Загружает данные через провайдеры типов объектов |
doSearch(SearchQuery $searchQuery) |
Запускает серверный поиск по зарегистрированным типам объектов |
getChildren(Item $parentItem) |
Загружает дочерние элементы для переданного элемента |
setPreselectedItems(array $preselectedItems) |
Задает заранее выбранные элементы |
loadPreselectedItems() |
Загружает заранее выбранные элементы |
shouldClearUnavailableItems() |
Возвращает true, если недоступные элементы нужно удалить из недавних |
getErrors() |
Возвращает ошибки типов объектов |
addError(EntityError $error) |
Добавляет ошибку типа объекта |
saveRecentItems(array $recentItems) |
Сохраняет выбранные элементы в историю недавних |
public function fillDialog(Dialog $dialog): void
{
$dialog->addTab(new Tab([
'id' => 'projects',
'title' => 'Проекты',
]));
$dialog->addItem(new Item([
'id' => 1,
'entityId' => 'project',
'title' => 'Проект внедрения',
'tabs' => 'projects',
]));
}
ItemCollection
Bitrix\UI\EntitySelector\ItemCollection хранит элементы диалога на сервере. Коллекцию возвращает Dialog::getItemCollection().
| Метод | Что делает |
|---|---|
add(Item $item) |
Добавляет элемент в коллекцию. Возвращает false, если элемент с таким entityId и id уже есть |
get(string $entityId, $itemId) |
Возвращает элемент по идентификатору типа объекта и идентификатору элемента |
has(Item $item) |
Возвращает true, если элемент уже есть в коллекции |
getAll() |
Возвращает массив всех элементов |
count() |
Возвращает количество элементов |
getEntityItems(string $entityId) |
Возвращает элементы одного типа объекта |
toArray() |
Возвращает элементы как массивы для передачи на клиент |
toJsObject() |
Возвращает JavaScript-представление массива элементов |
RecentCollection
Bitrix\UI\EntitySelector\RecentCollection хранит элементы вкладки «Последние». Коллекции создаются автоматически и доступны в провайдере через Dialog::getRecentItems() и Dialog::getGlobalRecentItems().
Для добавления элементов во вкладку «Последние» используйте Dialog::addRecentItem() или Dialog::addRecentItems().
| Метод | Что делает |
|---|---|
add(RecentItem $recentItem) |
Добавляет элемент в коллекцию, если такого элемента еще нет |
get(string $entityId, $itemId) |
Возвращает элемент по идентификатору типа объекта и идентификатору элемента |
has(RecentItem $recentItem) |
Возвращает true, если элемент уже есть в коллекции |
clear() |
Очищает коллекцию |
getByItem(Item $item) |
Возвращает недавний элемент по элементу диалога |
getAll() |
Возвращает массив всех недавних элементов |
count() |
Возвращает количество недавних элементов |
getEntityItems(string $entityId) |
Возвращает недавние элементы одного типа объекта |
При сериализации коллекция возвращает только элементы, для которых RecentItem::isLoaded() и RecentItem::isAvailable() возвращают true.
RecentItem
Bitrix\UI\EntitySelector\RecentItem представляет один элемент вкладки «Последние». Обычно объект создается внутри Dialog::addRecentItem() или Dialog::addRecentItems().
В конструктор передается массив с полями:
| Поле | Тип | Что делает |
|---|---|---|
id |
string или int |
Идентификатор элемента внутри типа объекта |
entityId |
string |
Идентификатор типа объекта. Значение приводится к нижнему регистру |
loaded |
boolean |
Помечает элемент как загруженный |
available |
boolean |
Помечает элемент как доступный для показа |
lastUseDate |
int |
Дата последнего выбора элемента |
| Метод | Что делает |
|---|---|
getId() |
Возвращает идентификатор элемента |
getEntityId() |
Возвращает идентификатор типа объекта |
getLastUseDate() |
Возвращает дату последнего выбора |
setLastUseDate(int $lastUseDate) |
Задает дату последнего выбора |
isLoaded() |
Возвращает true, если элемент загружен |
setLoaded(bool $flag) |
Задает признак загруженного элемента |
isAvailable() |
Возвращает true, если элемент доступен для показа |
setAvailable(bool $flag) |
Задает доступность элемента для показа |
При сериализации RecentItem возвращает пару [entityId, id].
PHP Item
Bitrix\UI\EntitySelector\Item — серверное представление элемента. Провайдер создает такие объекты и передает их в Dialog::addItem() или возвращает из getItems() и getPreselectedItems().
| Метод | Что делает |
|---|---|
getId() |
Возвращает идентификатор элемента |
getEntityId() |
Возвращает идентификатор типа объекта |
getEntityType() |
Возвращает тип элемента внутри объекта |
setEntityType(string $type) |
Задает тип элемента внутри объекта |
getTitle() |
Возвращает заголовок |
setTitle($title) |
Задает заголовок |
getSubtitle() |
Возвращает подзаголовок |
setSubtitle($subtitle) |
Задает подзаголовок |
getSupertitle() |
Возвращает текст над заголовком |
setSupertitle($supertitle) |
Задает текст над заголовком |
getCaption() |
Возвращает подпись |
setCaption($caption) |
Задает подпись |
setCaptionOptions(array $captionOptions) |
Задает параметры подписи |
getCaptionOptions() |
Возвращает параметры подписи |
getAvatar() |
Возвращает аватар |
setAvatar(?string $avatar) |
Задает аватар |
setAvatarOptions(array $avatarOptions) |
Задает параметры аватара |
getAvatarOptions() |
Возвращает параметры аватара |
getTextColor() |
Возвращает цвет текста |
setTextColor(?string $textColor) |
Задает цвет текста |
getLink() |
Возвращает ссылку элемента |
setLink(?string $link) |
Задает ссылку элемента |
getBadges() |
Возвращает бейджи |
addBadges(array $badges) |
Добавляет бейджи |
setBadges(array $badges) |
Задает бейджи |
getTabs() |
Возвращает вкладки элемента |
addTab($tabId) |
Добавляет вкладку элемента |
getChildren() |
Возвращает дочерние элементы |
addChildren(array $children) |
Добавляет массив дочерних элементов |
addChild(Item $item) |
Добавляет дочерний элемент |
setNodeOptions(array $nodeOptions) |
Задает параметры DOM-узла |
getNodeOptions() |
Возвращает параметры DOM-узла |
setTagOptions(array $nodeOptions) |
Задает параметры тега |
getTagOptions() |
Возвращает параметры тега |
isSelected() |
Возвращает true, если элемент выбран |
setSelected(bool $flag = true) |
Задает выбранное состояние |
isSearchable() |
Возвращает true, если элемент участвует в поиске |
setSearchable(bool $flag = true) |
Управляет участием элемента в поиске |
isSaveable() |
Возвращает true, если элемент сохраняется в недавних |
setSaveable(bool $flag = true) |
Управляет сохранением элемента в недавних |
isDeselectable() |
Возвращает true, если с элемента можно снять выбор |
setDeselectable(bool $flag = true) |
Управляет возможностью снять выбор |
isHidden() |
Возвращает true, если элемент скрыт |
setHidden(bool $flag = true) |
Управляет видимостью |
isLocked() |
Возвращает true, если элемент заблокирован |
setLocked(bool $flag = true) |
Управляет блокировкой |
setCustomData(array $customData) |
Задает пользовательские данные элемента |
getCustomData() |
Возвращает пользовательские данные элемента |
setSort(?int $sort) |
Задает сортировку |
getSort() |
Возвращает сортировку |
setDialog(Dialog $dialog) |
Привязывает элемент к серверному диалогу |
getDialog() |
Возвращает серверный диалог элемента |
toArray() |
Возвращает массив для передачи на клиент |
PHP Tab
Bitrix\UI\EntitySelector\Tab — серверное представление вкладки. Провайдер создает вкладки в fillDialog() и добавляет их в диалог через Dialog::addTab().
| Метод | Что делает |
|---|---|
getId() |
Возвращает идентификатор вкладки |
getTitle() |
Возвращает название вкладки |
setTitle($title) |
Задает название вкладки |
getIcon() |
Возвращает иконку вкладки |
setIcon(array $icon) |
Задает иконку вкладки |
getTextColor() |
Возвращает цвет текста |
setTextColor(array $textColor) |
Задает цвет текста |
getBgColor() |
Возвращает цвет фона |
setBgColor(array $bgColor) |
Задает цвет фона |
setVisible(bool $flag) |
Управляет видимостью вкладки |
isVisible() |
Возвращает true, если вкладка видима |
setItemOrder(array $order) |
Задает сортировку элементов на вкладке |
getItemOrder() |
Возвращает сортировку элементов на вкладке |
setItemMaxDepth(int $depth) |
Задает максимальную глубину вложенности |
getItemMaxDepth() |
Возвращает максимальную глубину вложенности |
setStub($stub) |
Задает заглушку вкладки |
getStub() |
Возвращает заглушку вкладки |
setStubOptions(array $options) |
Задает параметры заглушки |
getStubOptions() |
Возвращает параметры заглушки |
setHeader(string $header, array $options = []) |
Задает заголовок вкладки |
getHeader() |
Возвращает заголовок вкладки |
enableDefaultHeader() |
Включает показ стандартного заголовка |
disableDefaultHeader() |
Отключает показ стандартного заголовка |
canShowDefaultHeader() |
Возвращает true, если можно показать стандартный заголовок |
setFooter(string $footer, array $options = []) |
Задает футер вкладки |
getFooter() |
Возвращает футер вкладки |
enableDefaultFooter() |
Включает показ стандартного футера |
disableDefaultFooter() |
Отключает показ стандартного футера |
canShowDefaultFooter() |
Возвращает true, если можно показать стандартный футер |
setShowAvatars(bool $flag) |
Управляет показом аватаров на вкладке |
getShowAvatars() |
Возвращает настройку показа аватаров на вкладке |
PHP Entity
Bitrix\UI\EntitySelector\Entity — серверное представление типа объекта. Сервер создает его по настройкам entities и связывает с провайдером.
| Метод | Что делает |
|---|---|
Entity::create(array $entityOptions) |
Создает тип объекта по массиву настроек |
getId() |
Возвращает идентификатор типа объекта |
getOptions() |
Возвращает параметры провайдера |
getProvider() |
Возвращает провайдер типа объекта |
setProvider(BaseProvider $provider) |
Задает провайдер типа объекта |
getSubstituteEntityId() |
Возвращает идентификатор типа объекта-замены |
getFilters() |
Возвращает фильтры |
addFilter(BaseFilter $filter) |
Добавляет фильтр |
isSearchable() |
Возвращает true, если тип объекта участвует в поиске |
setSearchable(bool $flag = true) |
Управляет участием типа объекта в поиске |
hasDynamicSearch() |
Возвращает true, если включен серверный поиск |
setDynamicSearch(bool $flag = true) |
Управляет серверным поиском |
hasDynamicLoad() |
Возвращает true, если включена серверная загрузка |
setDynamicLoad(bool $flag = true) |
Управляет серверной загрузкой |
shouldFillRecentItems() |
Возвращает true, если провайдер может заполнять недавние элементы |
Подключить провайдер в JavaScript
Передайте тип объекта в entities. Для начальной загрузки используйте dynamicLoad, для серверного поиска — dynamicSearch.
import { Dialog } from 'ui.entity-selector';
const button = document.getElementById('project-selector-button');
if (button)
{
const dialog = new Dialog({
targetNode: button,
context: 'MY_MODULE_PROJECTS',
enableSearch: true,
entities: [
{
id: 'project',
dynamicLoad: true,
dynamicSearch: true,
},
],
preselectedItems: [
['project', 1],
],
});
}
При открытии диалога сервер найдет провайдер типа объекта project и загрузит элементы. При поиске диалог вызовет метод doSearch() провайдера.
Если провайдер не подключается, проверьте:
entities[].idв JavaScript совпадает сentityIdв настройках модуля;- класс провайдера доступен в модуле из
provider.moduleId; isAvailable()возвращаетtrueдля текущего пользователя и сценария;- для начальной загрузки включен
dynamicLoad, для серверного поиска —dynamicSearch; - стандартный тип объекта не требует собственного провайдера, используйте
entityIdиз статьи Стандартные провайдеры.