В первую очередь bitrix24 предназначен для работы с данными, какими бы они не были. В 99% случаев эти данные нужно отображать в виде списка с определенным набором функций (какие-то действия над элементами списка, постраничная навигация, поиск и тд). В этой статье я расскажу как с помощью штатных средств быстро создать список элементов с требуемым функционалом.
Если вам уже посчастливилось работать с bitrix24, то вероятно вы уже знакомы с используемым в системе способом отображения списочных данных. Компонент для отображения данных в табличном виде называется grid и выглядит следующем образом:

В основе примера используются компоненты для отображения панели фильтрации, кнопок управления и сам grid (bitrix:main.ui.grid). Попробуем реализовать компонент для отображения собственных элементов. В роли собственных элементов будут выступать пользователи портала, источником данных будет ORM модель \Bitrix\Main\UserTable.
Шаг 1 Создание структуры компонента
Начнём с создания структуры компонента. В директории /local/components/aclips/ создадим следующие файлы и каталоги:
- local/components/aclips/
-- base.grid/
--- class.php
--- templates/
----.default/
----- template.php
Шаг 2 Логика компонента
Всё поведение компонента описывается в файле class.php. Это будет класс, расширяющий базовый \CBitrixComponent. Для начала создадим «болванку», которую в дальнейшем будем дорабатывать:
<?php
namespace Aclips\Components;
class BaseGridComponent extends \CBitrixComponent
{
const GRID_ID = 'BASE_GRID';
const PAGE_SIZE = 15;
public function executeComponent()
{
$this->includeComponentTemplate();
}
}Краткое описание методов класса BaseGridComponent (типизация входных параметров и выходных значений не указана):
- public function executeComponent() — основной код компонента;
- public function getEntityRepository() — возвращает объект сущности (репозиторий) для получения данных;
- public function initNav($grid_options, $page_size) — получение объекта для постраничной навигации;
- public function getSorting($grid) — получение сортировки;
- public function getEntityFilter($grid_id, $grid_filter) — получение объекта для фильтрации;
- public function getEntitySelect() — получение списка полей, которые будут участвовать в выборке;
- public function getPreparedElement($fields) — метод для преобразования элементов
- public function getElementActions($fields) — получение действий для выполнения над элементом;
- private function getFilterFields($option = []) — получение полей фильтра;
- private function getGridColumns($option = []) — получение полей списка;
- private function prepareFilter($grid_id, $grid_filter) — преобразование данных, полученных из фильтра.
Константы класса:
- const GRID_ID — идентификатор списка (грида);
- const PAGE_SIZE — количество элементов, отображаемое на одной странице;
Подробнее остановимся только на некоторых методах.
Метод executeComponent
Работа данного метода сводится к получению и обработке данных, которые будут переданы в стандартные компоненты отображения фильтра и списка в шаблоне компонента.
public function executeComponent()
{
$grid_id = self::GRID_ID;
$grid_options = new Grid\Options($grid_id);
$grid_filter = $this->getFilterFields();
$entityRepository = $this->getEntityRepository();
$filter = $this->getEntityFilter($grid_id, $grid_filter);
$select = $this->getEntitySelect();
$sort = $this->getSorting($grid_options);
$page_size = $this->arParams['PAGE_SIZE'] ?? self::PAGE_SIZE;
$nav = $this->initNav($grid_options, $page_size);
$elements = $entityRepository::getList([
'filter' => $filter,
'select' => $select,
"order" => $sort,
"count_total" => true,
"offset" => $nav->getOffset(),
"limit" => $nav->getLimit()
]);
$nav->setRecordCount($elements->getCount());
$grid_rows = [];
foreach ($elements as $element) {
$prepared_element = $this->getPreparedElement($element);
$actions = $this->getElementActions($element);
$row = [
'id' => $element['ID'],
'data' => $element,
'columns' => $prepared_element,
'editable' => 'Y',
'actions' => $actions
];
$grid_rows[] = $row;
}
$this->arResult['NAV'] = $nav;
$this->arResult['GRID_ID'] = $grid_id;
$this->arResult['GRID_FILTER'] = $grid_filter;
$this->arResult['GRID_COLUMNS'] = $this->getGridColumns();
$this->arResult['ROWS'] = $grid_rows;
$this->includeComponentTemplate();
}
Метод getEntityRepository
Возвращает объект, отдающий данные. В зависимости от best replica watcheshttps://www.jana-fuchs.de/salon/article source типа объекта, реализация в методе executeComponent может меняться. В нашем примере мы используем объект от типа \Bitrix\Main\ORM\Data\DataManager.
public function getEntityRepository()
{
$entityReporitory = new \Bitrix\Main\UserTable();
return $entityReporitory;
}Метод getPreparedElement
Для обработки сырых (полученных из бд) данных каждый элемент попадает в данный метод. Например, у нас есть поле ACTIVE со значениями Y и N, а в списке мы хотим отображать словами «Пользователь активен» или «Пользователь не активен»
public function getPreparedElement($fields)
{
$fields['ACTIVE'] = $fields['ACTIVE'] == 'Y' ? 'Пользователь активен' : 'Пользователь не активен';
return $fields;
}
Метод getElementActions
Как уже было сказано, метод возвращает массив действий над записями. Каждый элемент действий содержит 3 свойства:
- text — название действия, отображаемое в контекстном меню;
- onclick — js действие, выполняемое при выборе пункта;
- default — флаг, отвечающий за действие, выполняемое при двойном клике по записи в списке.
public function getElementActions($fields)
{
$actions = [];
$actions[] = [
'text' => 'Открыть',
'onclick' => "alert('Выбран пункт Открыть')",
'default' => true
];
$actions[] = [
'text' => 'Удалить',
'onclick' => "alert('Выбран пункт Удалить')",
];
return $actions;
}
Метод getFilterFields
Возвращает массив элементов, которые должны отображаться в фильтре. Состоят элементы из:
- id — Идентификатор поля фильтра;
- name — Отображаемое название;
- type — Тип поля (влияет на способ отображения);
- default — флаг, отвечающий за отображение поля в фильтре по умолчанию.
У каждого типа могут быть свои дополнительные параметры.
private function getFilterFields()
{
$filterFields = [
[
'id' => 'NAME',
'name' => 'Имя',
'default' => true
],
[
'id' => 'ACTIVE',
'name' => 'Активность пользователя',
'type' => 'list',
'items' => [
'Y' => 'Пользователь активен',
'N' => 'Пользователь не активен'
],
'params' => [
'multiple' => 'Y'
],
'default' => true
],
[
'id' => 'DATE_REGISTER',
'name' => 'Дата регистрации',
'type' => 'date',
'default' => true
]
];
return $filterFields;
}
Метод getGridColumns
Массив отображаемых полей, содержащих:
- id — Идентификатор поля;
- name — Отображаемое название в списке;
- sort — Идентификатор поля, по которому будет проводиться сортировка;
- default — Флаг, отвечающий за отображение в списке по умолчанию.
private function getGridColumns()
{
$columns = [
[
'id' => 'NAME',
'name' => 'Имя',
'sort' => 'NAME',
'default' => true
],
[
'id' => 'ACTIVE',
'name' => 'Активность',
'sort' => 'ACTIVE',
'default' => true
],
[
'id' => 'DATE_REGISTER',
'name' => 'Дата регистрации',
'sort' => 'DATE_REGISTER',
'default' => true
]
];
return $columns;
}Метод prepareFilter
Формирует из полученных данных массив для фильтрации элементов.
Пример:
private function prepareFilter($grid_id, $grid_filter): array
{
$filter = [];
$filterOption = new \Bitrix\Main\UI\Filter\Options($grid_id);
$filterData = $filterOption->getFilter([]);
foreach ($filterData as $k => $v) {
$filter[$k] = $v;
}
$filterPrepared = \Bitrix\Main\UI\Filter\Type::getLogicFilter($filter, $grid_filter);
if (!empty($filter['FIND'])) {
$findFilter = [
'LOGIC' => 'OR',
[
'%NAME' => $filter['FIND']
]
];
if (!empty($filterPrepared)) {
$filterPrepared[] = $findFilter;
} else {
$filterPrepared = $findFilter;
}
}
return $filterPrepared;
}Шаг 3 Шаблон отображения
Логики описаны, данные получены. Остаётся передать сформированные параметры в компоненты, отвечающие за построение фильтра (bitrix:main.ui.filter) и списка (bitrix:main.ui.grid).
Фильтр
На момент написания статьи доступен еще один способ отображения фильтра, через Toolbar модуля ui. Мне этот способ нравится больше, по этому рассматривать в примере будем именно его.
Добавим в шаблон код:
<?php
/**
* Toolbar filter
**/
\Bitrix\Main\Loader::includeModule('ui');
\Bitrix\UI\Toolbar\Facade\Toolbar::addFilter([
'FILTER_ID' => $arResult['GRID_ID'],
'GRID_ID' => $arResult['GRID_ID'],
'FILTER' => $arResult['GRID_FILTER'],
'ENABLE_LIVE_SEARCH' => true,
'ENABLE_LABEL' => true
]);
Данный способ удобен тем, что на страницу добавляется компонент, в который можно без особого труда добавить какие-либо элементы управления.
Для добавления кнопки рядом с полем ввода нужно создать экземпляр этой самой кнопки и передать её в Toolbar.
/**
* Toolbar buttons
**/
$addButton = new \Bitrix\UI\Buttons\AddButton([
"click" => new \Bitrix\UI\Buttons\JsCode(
"alert('Кнопка нажата')"
),
"text" => "Важная кнопка"
]);
\Bitrix\UI\Toolbar\Facade\Toolbar::addButton($addButton);
Подробнее ознакомиться с кнопками и прочими элементами интерфейса можно в документации.
Список
Вызываем компонент списка и передаём в него параметры. У компонента настроек много и описывать их в данной статье не имеет смысла. При желании и небольшом усилии можно легко разобраться за что отвечает каждый из параметров :).
Код вызова штатного компонента списка:
<?php $APPLICATION->IncludeComponent('bitrix:main.ui.grid', '', [
'GRID_ID' => $arResult['GRID_ID'],
'COLUMNS' => $arResult['GRID_COLUMNS'],
'ROWS' => $arResult['ROWS'],
'NAV_OBJECT' => $arResult['NAV'],
'AJAX_MODE' => 'Y',
'AJAX_ID' => \CAjax::getComponentID('bitrix:main.ui.grid', '.default', ''),
'AJAX_OPTION_JUMP' => 'N',
'SHOW_ROW_CHECKBOXES' => false,
'SHOW_CHECK_ALL_CHECKBOXES' => false,
'SHOW_ROW_ACTIONS_MENU' => true,
'SHOW_GRID_SETTINGS_MENU' => true,
'SHOW_NAVIGATION_PANEL' => true,
'SHOW_PAGINATION' => true,
'SHOW_SELECTED_COUNTER' => false,
'SHOW_TOTAL_COUNTER' => false,
'SHOW_PAGESIZE' => false,
'SHOW_ACTION_PANEL' => false,
'ALLOW_COLUMNS_SORT' => true,
'ALLOW_COLUMNS_RESIZE' => true,
'ALLOW_HORIZONTAL_SCROLL' => true,
'ALLOW_SORT' => true,
'ALLOW_PIN_HEADER' => true,
'AJAX_OPTION_HISTORY' => 'N',
"ENABLE_COLLAPSIBLE_ROWS" => true
], $component); ?>
Итог
Описанным выше способом можно собрать базовый компонент, который сэкономит очень много времени, нервов и сил. Сам компонент можно скачать из репозитория. Обращаю внимание, что это всего лишь «шаблонный» компонент, используя который можно решить свои задачи. Опираясь на него я продемонстрирую, как я использую javascript в компонентах bitrix24 в следующих статьях.