Гриды и фильтры в 1С-Битрикс

1С-Битрикс
Гриды и фильтры в 1С-Битрикс

Скорее всего, вы сталкивались с задачей вывести в публичной части (да и в административном разделе) проекта какую-либо служебную информацию для пользователей в табличном виде. Наверняка, вы писали собственные шаблоны для компонентов и потом добавляли костыли для фильтрации и сортировки этих данных.

Начиная с версии 17.0.7 Главного модуля 1С-Битрикс вышли два компонента: bitrix:main.ui.filter и bitrix:main.ui.grid с классами Bitrix\Main\UI\Filter и Bitrix\Main\Grid (есть даже в редакции «Первый сайт»).

Гриды

За вывод грида отвечает компонент bitrix:main.ui.grid. Параметры:

Параметр Тип Описание
GRID_ID string Идентификатор грида (такой же, как у фильтра)
COLUMNS array Массив с заголовками грида
ROWS array Массив с значениями грида, действиями в контекстном меню
SHOW_ROW_CHECKBOXES bool Показывать чекбоксы у строк для множественных действий
NAV_OBJECT object Объект для постраничной навигации
AJAX_MODE string Использовать ли ajax режим
AJAX_ID string Ajax ID Берётся из компонента фильтра
PAGE_SIZES array Массив для выпадающего списка с выбором кол-ва элементов на странице
AJAX_OPTION_JUMP string
AJAX_OPTION_JUMP string
SHOW_CHECK_ALL_CHECKBOXES bool Показывать "Выбрать все"
SHOW_ROW_ACTIONS_MENU bool
SHOW_GRID_SETTINGS_MENU bool
SHOW_NAVIGATION_PANEL bool
SHOW_PAGINATION bool
SHOW_SELECTED_COUNTER bool Показывать "Выбрано элементов"
SHOW_TOTAL_COUNTER bool Показывать "Всего элементов"
SHOW_PAGESIZE bool Выводить выпадающий список с выбором кол-ва элементов на странице
SHOW_ACTION_PANEL bool
ALLOW_COLUMNS_SORT bool
ALLOW_COLUMNS_RESIZE bool
ALLOW_HORIZONTAL_SCROLL bool Будет доступен горизонтальный скролл
ALLOW_SORT bool Разрешить сортировку
ALLOW_PIN_HEADER bool Разрешать закреплять шапку грида
AJAX_OPTION_HISTORY bool

Пример вызова компонента:

1<?php
2 
3$grid_options = new Bitrix\Main\Grid\Options('report_list');
4$sort = $grid_options->GetSorting(['sort' => ['ID' => 'DESC'], 'vars' => ['by' => 'by', 'order' => 'order']]);
5$nav_params = $grid_options->GetNavParams();
6 
7$nav = new Bitrix\Main\UI\PageNavigation('report_list');
8$nav->allowAllRecords(true)
9 ->setPageSize($nav_params['nPageSize'])
10 ->initFromUri();
11 
12// Кнопка удалить
13$onchange = new Onchange();
14$onchange->addAction(
15 [
16 'ACTION' => Actions::CALLBACK,
17 'CONFIRM' => true,
18 'CONFIRM_APPLY_BUTTON' => 'Подтвердить',
19 'DATA' => [
20 ['JS' => 'Grid.removeSelected()']
21 ]
22 ]
23);
24 
25$APPLICATION->IncludeComponent('bitrix:main.ui.grid', '', [
26 'GRID_ID' => 'report_list',
27 'COLUMNS' => [
28 ['id' => 'ID', 'name' => 'ID', 'sort' => 'ID', 'default' => true],
29 ['id' => 'DATE', 'name' => 'Дата', 'sort' => 'DATE', 'default' => true],
30 ['id' => 'AMOUNT', 'name' => 'Сумма', 'sort' => 'AMOUNT', 'default' => true],
31 ['id' => 'PAYER_INN', 'name' => 'ИНН Плательщика', 'sort' => 'PAYER_INN', 'default' => true],
32 ['id' => 'PAYER_NAME', 'name' => 'Плательщик', 'sort' => 'PAYER_NAME', 'default' => true],
33 ['id' => 'IS_SPEND', 'name' => 'Тип операции', 'sort' => 'IS_SPEND', 'default' => true],
34 ],
35 'ROWS' => $list, //Самое интересное, опишем ниже
36 'SHOW_ROW_CHECKBOXES' => true,
37 'NAV_OBJECT' => $nav,
38 'AJAX_MODE' => 'Y',
39 'AJAX_ID' => \CAjax::getComponentID('bitrix:main.ui.grid', '.default', ''),
40 'PAGE_SIZES' => [
41 ['NAME' => "5", 'VALUE' => '5'],
42 ['NAME' => '10', 'VALUE' => '10'],
43 ['NAME' => '20', 'VALUE' => '20'],
44 ['NAME' => '50', 'VALUE' => '50'],
45 ['NAME' => '100', 'VALUE' => '100']
46 ],
47 'AJAX_OPTION_JUMP' => 'N',
48 'SHOW_CHECK_ALL_CHECKBOXES' => true,
49 'SHOW_ROW_ACTIONS_MENU' => true,
50 'SHOW_GRID_SETTINGS_MENU' => true,
51 'SHOW_NAVIGATION_PANEL' => true,
52 'SHOW_PAGINATION' => true,
53 'SHOW_SELECTED_COUNTER' => true,
54 'SHOW_TOTAL_COUNTER' => true,
55 'SHOW_PAGESIZE' => true,
56 'SHOW_ACTION_PANEL' => true,
57 'ACTION_PANEL' => [
58 'GROUPS' => [
59 'TYPE' => [
60 'ITEMS' => [
61 [
62 'ID' => 'set-type',
63 'TYPE' => 'DROPDOWN',
64 'ITEMS' => [
65 ['VALUE' => '', 'NAME' => '- Выбрать -'],
66 ['VALUE' => 'plus', 'NAME' => 'Поступление'],
67 ['VALUE' => 'minus', 'NAME' => 'Списание']
68 ]
69 ],
70 [
71 'ID' => 'edit',
72 'TYPE' => 'BUTTON',
73 'TEXT' => 'Редактировать',
74 'CLASS' => 'icon edit',
75 'ONCHANGE' => ''
76 ],
77 [
78 'ID' => 'delete',
79 'TYPE' => 'BUTTON',
80 'TEXT' => 'Удалить',
81 'CLASS' => 'icon remove',
82 'ONCHANGE' => $onchange->toArray()
83 ],
84 ],
85 ]
86 ],
87 ],
88 'ALLOW_COLUMNS_SORT' => true,
89 'ALLOW_COLUMNS_RESIZE' => true,
90 'ALLOW_HORIZONTAL_SCROLL' => true,
91 'ALLOW_SORT' => true,
92 'ALLOW_PIN_HEADER' => true,
93 'AJAX_OPTION_HISTORY' => 'N'
94]);

Передаём данные в грид:

1<?php
2 
3$list = [
4 [
5 'data' => [ //Данные ячеек
6 "ID" => 1,
7 "NAME" => "Название 1",
8 "AMOUNT" => 1000,
9 "PAYER_NAME" => "Плательщик 1"
10 ],
11 'actions' => [ //Действия над ними
12 [
13 'text' => 'Редактировать',
14 'onclick' => 'document.location.href="/accountant/reports/1/edit/"'
15 ],
16 [
17 'text' => 'Удалить',
18 'onclick' => 'document.location.href="/accountant/reports/1/delete/"'
19 ]
20 
21 ],
22 ], [
23 'data' => [ //Данные ячеек
24 "ID" => 2,
25 "NAME" => "Название 2",
26 "AMOUNT" => 3000,
27 "PAYER_NAME" => "Плательщик 2"
28 ],
29 'actions' => [ //Действия над ними
30 [
31 'text' => 'Редактировать',
32 'onclick' => 'document.location.href="/accountant/reports/2/edit/"'
33 ],
34 [
35 'text' => 'Удалить',
36 'onclick' => 'document.location.href="/accountant/reports/2/delete/"'
37 ]
38 ],
39 ]
40];

Результат вывода:

Панель действий ACTION_PANEL:

Фильтр

За фильтрацию отвечает компонент bitrix:main.ui.filter. Его параметры:

Параметр Тип Описание
FILTER_ID string Идентификатор фильтра (должен быть уникальным)
GRID_ID string Идентификатор грида к которому применяем фильтр
FILTER array Массив с полями для фильтрации
ENABLE_LABEL bool Показывать название полей или нет
ENABLE_LIVE_SEARCH bool Будет ли доступна live-фильтрация

Пример вызова:

1<?php
2 
3$APPLICATION->IncludeComponent('bitrix:main.ui.filter', '', [
4 'FILTER_ID' => 'report_list',
5 'GRID_ID' => 'report_list',
6 'FILTER' => [
7 ['id' => 'DATE', 'name' => 'Дата', 'type' => 'date'],
8 ['id' => 'IS_SPEND', 'name' => 'Тип операции', 'type' => 'list', 'items' => ['' => 'Любой', 'P' => 'Поступление', 'M' => 'Списание'], 'params' => ['multiple' => 'Y']],
9 ['id' => 'AMOUNT', 'name' => 'Сумма', 'type' => 'number'],
10 ['id' => 'PAYER_INN', 'name' => 'ИНН Плательщика', 'type' => 'number'],
11 ['id' => 'PAYER_NAME', 'name' => 'Плательщик'],
12 ],
13 'ENABLE_LIVE_SEARCH' => true,
14 'ENABLE_LABEL' => true
15]);

Результат:

Также фильтры можно сохранять для быстрого использования:

Связка фильтра и грида

Чтобы пробросить данные из фильтра в грид, необходимо собрать фильтр:

1<?php
2 
3$filter = [];
4$filterOption = new Bitrix\Main\UI\Filter\Options('report_list');
5$filterData = $filterOption->getFilter([]);
6foreach ($filterData as $k => $v) {
7 $filter[$k] = $v;
8}

Фильтрация любых данных

Связка Фильтр-Грид работает в 1С-Битрикс по умолчанию, но иногда хочется такую фильтрацию добавить к своим данным, например, к выводу графика:

Для того, чтобы это заработало, необходимо «подписаться» на событие применения фильтра:

1<script type="text/javascript">
2BX.addCustomEvent('BX.Main.Filter:apply', BX.delegate(function (command, params) {
3 var workarea = $('#' + command); // в command будет храниться GRID_ID из фильтра
4 
5 $.post(window.location.href, function(data){
6 workarea.html($(data).find('#' + command).html());
7 })
8}));
9</script>

Хаки

Почему-то 1С-Битрикс в своих компонентах автоматически не подцепляет css-файл со стилями кнопок (на момент написания статьи), поэтому перед вызовом компонентов, рекомендуется добавить css-файл вручную:

1<?php
2 
3Bitrix\Main\Page\Asset::getInstance()->addCss('/bitrix/css/main/grid/webform-button.css');

Чтобы обновить грид без перезагрузки страницы, воспользуйтесь методом:

1<script type="text/javascript">
2var reloadParams = { apply_filter: 'Y', clear_nav: 'Y' };
3var gridObject = BX.Main.gridManager.getById('report_list'); // Идентификатор грида
4 
5if (gridObject.hasOwnProperty('instance')){
6 gridObject.instance.reloadTable('POST', reloadParams);
7}
8</script>