Гриды и фильтры в Битриксе
Последние записи
В статье описается пример размещения связанного фильтра и таблицы с фильтрацией реальных данных из типичного highloadблока без сложных выборок
Пример не является полностью рабочим, поскольку часть функционала в него добавлена только для иллюстрации способов добавления кнопок или возможностей. Обработчики вам придется написать самим. Но основной код является рабочим и при правильном переносе должен работать.
Начиная с версии 17.0.7
в Битрикс появились два компонента bitrix:main.ui.filter
и bitrix:main.ui.grid
с классами Bitrix\Main\UI\Filter
и Bitrix\Main\Grid
(есть даже в редакции «Первый сайт»).
Фильтр bitrix:main.ui.filter
Параметры:
FILTER_ID | string Идентификатор фильтра (должен быть уникальным) |
GRID_ID | string Идентификатор грида к которому применяем фильтр |
FILTER | array Массив с полями для фильтрации |
ENABLE_LABEL | bool Показывать название полей или нет |
ENABLE_LIVE_SEARCH | bool Будет ли доступна live-фильтрация |
Пример вызова:
use Bitrix\Main\Grid\Options as GridOptions;
use Bitrix\Main\UI\PageNavigation;
use \Bitrix\Main\Type\DateTime as DT;
use Bitrix\Main\Loader;
use Bitrix\Highloadblock as HL;
$grid_id = $filter_id = 'CLIENTS_GRID';
$APPLICATION->IncludeComponent('bitrix:main.ui.filter', '', [
'FILTER_ID' => $filter_id,
'GRID_ID' => $grid_id,
'FILTER' => [
['id' => 'DEAL_ID', 'name' => 'ID сделки', 'type'=>'text', 'default' => true],
['id' => 'DEAL_STAGE', 'name' => 'Стадия сделки', 'type' => 'list', 'items' => [
'18' => '*В обработке',
'19' => '*Договор подписан'
], 'params' => ['multiple' => 'Y'], 'default' => true],
['id' => 'DEAL_START_DATE', 'name' => 'Дата начала сделки', 'type' => 'list', 'items' => [
'1' => '0-7 дней',
'2' => '0-14 дней',
'3' => '0-30 дней',
'4' => '0-2 мес',
'5' => '0-6 мес',
], 'params' => ['multiple' => 'N'], 'default' => true],
],
'ENABLE_LIVE_SEARCH' => true,
'ENABLE_LABEL' => true,
'VALUE_REQUIRED_MODE' => true,
'FILTER_PRESETS' => [
"defaultPreset" => [
"name" => 'Пресет по сделкам',
"default" => true, // если true - пресет по умолчанию
"fields" => [
"DEAL_STAGE" => "24",
"NAME" => "Новосибирск",
]
],
"PRESET_NEW" => [
"name" => 'Пресет новый',
"default" => false, // если true - пресет по умолчанию
"fields" => [
"DEAL_ID" => "17534",
]
],
]
]);
Связка фильтра и таблицы. Чтобы пробросить данные из фильтра в таблицу, необходимо собрать фильтр:
foreach ($filterFields as $k => $v) {
if($k == 'FIND' && $v)
$filterData['NAME'] = "%".$v."%";
else
$filterData[$k] = $v;
}
$mainFilter = [];
//Стадия сделки
if($filterData['DEAL_STAGE'])
$mainFilter['UF_STAGE_ID'] = $filterData['DEAL_STAGE'];
//ID сделки
if($filterData['DEAL_ID'])
$mainFilter['UF_ID'] = $filterData['DEAL_ID'];
//Обработка даты
if($filterData['DEAL_START_DATE'][0]){
$format = "Y-m-d H:i:s";
$today = date($format);
$interval = 0;
switch ($filterData['DEAL_START_DATE'][0]){
case '1':
$interval = 7;
break;
case '2':
$interval = 14;
break;
case '3':
$interval = 30;
break;
case '4':
$interval = 60;
break;
case '5':
$interval = 180;
break;
}
$data = \CLASS\Helper\Date::dateMinus($today, $format, 'days', $interval);
$mainFilter['>UF_BEGINDATE'] = DT::createFromTimestamp(strtotime($data));
}
bitrix:main.ui.grid
Список параметров:
GRID_ID | string Идентификатор грида (такой же указывали у фильтра) |
COLUMNS | array Массив с head таблицы 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 |
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 |
Пример вызова компонента:
$grid_options = new GridOptions($grid_id);
$sort = $grid_options->GetSorting(['sort' => ['DATE_CREATE' => 'DESC'], 'vars' => ['by' => 'by', 'order' => 'order']]);
$nav_params = $grid_options->GetNavParams();
$nav = new PageNavigation($grid_id);
$nav->allowAllRecords(true)
->setPageSize($nav_params['nPageSize'])
->initFromUri();
if ($nav->allRecordsShown())
$nav_params = false;
else
$nav_params['iNumPage'] = $nav->getCurrentPage();
$getListOptions = array(
"select" => ['ID', "UF_BEGINDATE", 'UF_TITLE', 'UF_STAGE_ID'],
"order" => ["ID" => "DESC"],
"filter" => $mainFilter,
'limit' => $nav_params['nPageSize'],
'offset' => $nav_params['iNumPage'] - 1,
'runtime' => $runtimes ? $runtimes : '',
'count_total' => true
);
Loader::includeModule("highloadblock");
$hlblock = HL\HighloadBlockTable::getById(15)->fetch();
$entity = HL\HighloadBlockTable::compileEntity($hlblock);
$entity_data_class = $entity->getDataClass();
$dealsData = $entity_data_class::getList($getListOptions);
$dealsCount = $dealsData->getCount();
$dealsData = $dealsData->fetchAll();
$nav->setRecordCount($dealsCount);
foreach($dealsData as $k => $row) {
$list[] = [
'data' => [
"ID" => $row['ID'],
"DEAL_START" => $row['UF_BEGINDATE'],
"DEAL_NAME" => $row['UF_TITLE'],
"DEAL_STATUS" => $row['UF_STAGE_ID'],
],
'default_action' => [
"href" => '/bitrix/admin/iblock_element_edit.php?IBLOCK_ID=2&type=content&lang=ru&ID=4&find_section_section=-1&WF=Y',
"title" => 'Редактировать элемент',
],
'actions' => [
[
'text' => 'Редактировать',
'default' => true,
'onclick' => vsprintf("contextMenuGridAction.actionEdit(%d, '%s')", [
'ID' => $row['ID'],
'NAME' => $row['NAME']
])
],
[
'text' => $row['ACTIVE'] == 'Y'
? 'Деактивировать'
: 'Активировать',
'default' => true,
'onclick' => $row['ACTIVE'] == 'Y'
? "contextMenuGridAction.actionDeactivate($row[ID])"
: "contextMenuGridAction.actionActivate($row[ID])"
],
[
'delimiter' => true,
],
[
'text' => 'Открыть на сайте',
'default' => true,
'onclick' => "contextMenuGridAction.actionOpenOnSite('$row[NEW_URL]');"
],
[
'delimiter' => true,
],
[
'text' => 'Создать символьный код',
'default' => true,
'onclick' => "if(confirm('Вы уверены, что хотите изменить символьный код элемента? Это может повлиять на ссылку, по которой на сайте отображается элемент.')) BX.Main.gridManager.getById('tbl_iblock_element_b7d3215a9c5d7a3446fc85e1a5877fc2').instance.reloadTable('POST', {'action_button_tbl_iblock_element_b7d3215a9c5d7a3446fc85e1a5877fc2':'code_translit','ID':'4','IBLOCK_ID':'2','type':'content','lang':'ru','find_section_section':'-1'})"
],
[
'delimiter' => true,
],
[
'text' => 'Удалить',
'default' => true,
'onclick' => "contextMenuGridAction.actionDelete($row[ID])"
],
]
];
}
$columns = [];
$columns[] = ['id' => 'DEAL_START', 'name' => 'Дата начала сделки', 'sort' => 'DEAL_START', 'content' => 'Дата начала сделки', 'title' => 'Дата начала сделки', 'column_sort' => 100, 'default' => true];
$columns[] = ['id' => 'DEAL_NAME', 'name' => 'Название сделки', 'sort' => 'DEAL_NAME', 'content' => 'Название сделки', 'title' => 'Название сделки', 'column_sort' => 200, 'default' => true];
$columns[] = ['id' => 'DEAL_STATUS', 'name' => 'Статус сделки', 'sort' => 'DEAL_STATUS', 'content' => 'Статус сделки', 'title' => 'Статус сделки', 'column_sort' => 300, 'default' => true];
$gridParams = [
'GRID_ID' => $grid_id,
'COLUMNS' => $columns,
'ROWS' => $list,
'FOOTER' => [
'TOTAL_ROWS_COUNT' => $dealsCount,
],
'SHOW_ROW_CHECKBOXES' => false,
'NAV_OBJECT' => $nav,
'AJAX_MODE' => 'Y',
'AJAX_ID' => \CAjax::getComponentID('bitrix:main.ui.grid', '.default', ''),
'PAGE_SIZES' => [
['NAME' => "5", 'VALUE' => '5'],
['NAME' => '10', 'VALUE' => '10'],
['NAME' => '20', 'VALUE' => '20'],
['NAME' => '50', 'VALUE' => '50'],
['NAME' => '100', 'VALUE' => '100']
],
'AJAX_OPTION_JUMP' => 'N',
'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' => true,
'SHOW_TOTAL_COUNTER' => true,
'SHOW_PAGESIZE' => true,
'SHOW_ACTION_PANEL' => true,
'ALLOW_COLUMNS_SORT' => true,
'ALLOW_COLUMNS_RESIZE' => true,
'ALLOW_HORIZONTAL_SCROLL' => true,
'ALLOW_SORT' => true,
'ALLOW_PIN_HEADER' => true,
'AJAX_OPTION_HISTORY' => 'N',
'ACTION_PANEL' => [
'GROUPS' => [
'TYPE' => [
'ITEMS' => [
[
'ID' => 'set-type',
'TYPE' => 'DROPDOWN',
'ITEMS' => [
['VALUE' => '', 'NAME' => '- Выбрать -'],
['VALUE' => 'plus', 'NAME' => 'Поступление'],
['VALUE' => 'minus', 'NAME' => 'Списание']
]
],
[
'ID' => 'edit',
'TYPE' => 'BUTTON',
'TEXT' => 'Редактировать',
'CLASS' => 'icon edit',
// 'ONCHANGE' => $onchange->toArray()
],
[
'ID' => 'delete',
'TYPE' => 'BUTTON',
'TEXT' => 'Удалить',
'CLASS' => 'icon remove',
//'ONCHANGE' => $onchange->toArray()
],
],
]
],
],
];
$APPLICATION->IncludeComponent('bitrix:main.ui.grid', '', $gridParams);
?>
<script>
BX.ready(function ()
{
var gridObject = BX.Main.gridManager.getById('<?= $grid_id ?>');
if (gridObject.hasOwnProperty('instance')) {
gridObject.instance.reloadTable(null, null);
}
})
</script>
<script>
BX.ready(function () {
//Пример перехвата события применения фильтра
BX.addCustomEvent('BX.Main.Filter:apply', BX.delegate(function (command, params) {
//var workarea = $('#' + command); // в command будет храниться GRID_ID из фильтра
}));
});
var contextMenuGridAction = new FilterUI.ContextMenuInnerGrid();
</script>
Фильтрация любых данных
Связка Фильтр-Таблица работает в Битриксе по-умолчанию, но иногда хочется такую фильтрацию добавить к своим данным, например, к выводу графика
Для того, чтобы это заработало, необходимо «подписаться» на событие применения фильтра:
<script type="text/javascript">
BX.addCustomEvent('BX.Main.Filter:apply', BX.delegate(function (command, params) {
var workarea = $('#' + command); // в command будет храниться GRID_ID из фильтра
$.post(window.location.href, function(data){
workarea.html($(data).find('#' + command).html());
})
}));
</script>
Хаки
Почему-то Битрикс в своих компонентах автоматически не подцепляет css-файл со стилями кнопок (на момент написания статьи), поэтому перед вызовом компонентов, рекомендуется добавить css-файл вручную:
Bitrix\Main\Page\Asset::getInstance()->addCss('/bitrix/css/main/grid/webform-button.css');
Чтобы обновить грид без перезагрузки страницы, воспользуйтесь методом:
<script type="text/javascript">
var reloadParams = { apply_filter: 'Y', clear_nav: 'Y' };
var gridObject = BX.Main.gridManager.getById('report_list'); // Идентификатор грида
if (gridObject.hasOwnProperty('instance')){
gridObject.instance.reloadTable('POST', reloadParams);
}
</script>
Стоит ознакомиться:
Комментарии