Гриды и фильтры в Битриксе
Rus
Eng
Гриды и фильтры в Битриксе

В статье описается пример размещения связанного фильтра и таблицы с фильтрацией реальных данных из типичного 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>

 

Стоит ознакомиться:

Комментарии

Комментариев еще нет, Вы можете стать первым кто его оставит

Оставьте комментарий

На сайте используется система премодерирования комментариев, поэтому ваше сообщение будет опубликовано лишь после одобрения модератором

Вы отвечаете на комментарий пользователя

Отправить

ОБРАТНАЯ СВЯЗЬ

Напишите мне

Вы разрабатываете новый сервис, вносите доработки в существующий и хотите лучше чем у конкурентов? Вы обратились по адресу. Предлагаю вам комплексную разработку сайтов студийного уровня. У меня вы можете заказать дизайн, верстку, програмированние, разработку нетрадиционного функционала, реализацию связи между CMS, CRM и Data Analitics, а так же все остальное касаемое сайтов, кроме продвижения.

Обращайтесь, я всегда проконсультирую по всем вопросам и помогу подобрать наиболее эффективное решение для Вашего бизнеса. Я занимаюсь созданием сайтов в Новосибирске и в других регионах России, также работаю со странами СНГ. Вы останетесь довольны нашим сотрудничеством

Во время отправки произошла ошибка, пожалуйста попробуйте еще раз через некоторое время
Сообщение отправлено успешно

Телефоны

+7(993) 007-18-96

Email

info@tichiy.ru

Адрес

Россия, г. Москва

Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта

Написать мне
Отправить
Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта
Отправка успешна!
Thank you for your feedback. I will answer you within the next working hours
Отправка не удалась
Во время отправки запроса произошла ошибка. Пожалуйста, подождите и попробуйте снова через некоторое время или свяжитесь со мной