В первую очередь 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 в следующих статьях.