Панель действий
В настоящий момент продукт имеет 2 вида панели: первый (классический) - структура передаваемая в ключе ACTION_PANEL
, вторая - JS действия на основе расширения ui.actionpanel
(можно увидеть в канбан представлении). В текущей статье мы будем рассматривать панель действий в классическом представлении.
Панель действий инструмент для проведения групповых операций.
Вся панель состоит из так называем групп действий, если описывать на мета-языке в параметрах компонента это выглядит следующим образом:
// ... bitrix:main.ui.grid parameters
'ACTION_PANEL' => [
'GROUPS' => [
// .. groups,
]
],
// ... bitrix:main.ui.grid parameters
В свою очередь каждая группа это набор из двух параметров:
-
CLASS
(string) - строка, которая добавляетсяclass
-аттрибут ячейки действия -
ITEMS
(array) - список элементов группы
Давайте посмотрим пример простой группы - обычный select с вариантами выбор без какой-либо бизнес-логики:
'SHOW_ROW_CHECKBOXES' => true,
'SHOW_CHECK_ALL_CHECKBOXES' => true,
'ACTION_PANEL' => [
'GROUPS' => [
[
'CLASS' => 'some-css-td-class',
'ITEMS' => [
[
'ID' => 'set-type',
'TYPE' => 'DROPDOWN',
'ITEMS' => [
['VALUE' => '', 'NAME' => '- Выбрать -'],
['VALUE' => 'plus', 'NAME' => 'Поступление'],
['VALUE' => 'minus', 'NAME' => 'Списание']
]
],
],
],
],
],
Элемент группы
Мы уже обсудили, что каждая группа состоит набора элементов, а из чего состоит элемент? Технически элемент представляет собой ассоциативный массив и каждый такой массив содержит набор обязательных полей (в числе которых - тип элемента) и набор уникальных полей для каждого типа элемента.
Обязательные поля:
-
ID
(string) - уникальный идентификатор действия. По совместительству идентификатор dom node с управляющим элементом. -
TYPE
(enum) - тип поля (см. ниже допустимые типы полей) -
VALUE
(mixed) - значение
Опциональные поля:
-
DISABLED
(bool) - Состояние элемента (false по-умолчанию) -
ONCHANGE
(mixed) - обработчик действия (см Обработчик действия)
Допустимые типы полей
Допустимые типы полей, перечислены константами в классе Bitrix\Main\Grid\Panel\Types
.
В их число входят:
- Флаг (
CHECKBOX
) - Список (
DROPDOWN
) - Произвольное (
CUSTOM
) - Строка (
TEXT
) - Кнопка (
BUTTON
) - Ссылка (
LINK
) - Дата (
DATE
) - Скрытое (
HIDDEN
)
CHECKBOX
)
Флаг (Код отображения флага (чек-бокса) выглядит следующим образом:
[
'ID' => 'easy-checkbox',
'NAME' => 'checkbox-input-name',
'TYPE' => 'CHECKBOX',
'VALUE' => 'Y',
'TITLE' => 'Текст при наведении',
'LABEL' => 'Описание справа',
'CHECKED' => false,
]
Пояснение к параметрам:
-
CHECKED
(bool) - состояние чекбокса на момент инициализации страницы -
VALUE
(string) - значение input-ноды
DROPDOWN
)
Список (Пример кода отвечающего на выпадающий список:
[
'ID' => 'set-type',
'TYPE' => 'DROPDOWN',
'ITEMS' => [
['VALUE' => '', 'NAME' => '- Выбрать -'],
['VALUE' => 'plus', 'NAME' => 'Поступление'],
['VALUE' => 'minus', 'NAME' => 'Списание']
]
],
TEXT
)
Строка ([
'ID' => 'string-input',
'TYPE' => 'TEXT',
'LABEL' => 'Input label',
'PLACEHOLDER' => 'Type some str..',
'VALUE' => '',
'TITLE' => 'Displayed when hover'
]
BUTTON
)
Кнопка ([
'ID' => 'some-btn',
'TYPE' => 'BUTTON',
'TEXT' => 'Click me!',
'TITLE' => 'Displayed when hover'
]
LINK
)
Ссылка ([
'ID' => 'goto',
'TYPE' => 'LINK',
'TEXT' => 'Ссылка',
'HREF' => '/some-link.php',
'CLASS' => 'awesome-css-class'
]
DATE
)
Дата ([
'ID' => 'date-and-time-input',
'TYPE' => 'DATE',
'TIME' => true,
'PLACEHOLDER' => '10.10.2023'
'VALUE' => '',
]
Примечание к полям:
-
TIME
(bool) - нужно ли выводить дополнительные поля для времени
CUSTOM
)
Произвольное ([
'ID' => 'my-cusom-html-area',
'TYPE' => 'CUSTOM',
'VALUE' => 'Yeah! It is custom data - <button type="button" onclick="alert(\'It works!\')">Call alert!</button>'
]
Обработчик действия
Сами по себе элементы не представляют особого интереса - важную часть составляют именно обработчики действия изменения, которые оказывают влияние на всю панель выполняя определенные операции.
Строго говоря, название ONCHANGE
немного вводит в заблуждение - в HTML есть событие change
и одноименный html-аттрибут onchange
, который имеет мало общего в представленном механизме. Рассматривая ONCHANGE
ключ нужно помнить что это набор операций, выполняемых друг за другом.
Каждая операция состоит из двух обязательных параметров:
-
ACTION
(enum) - один из видов действия над панелью описывающий поведение. -
DATA
(array) - дополнительная информация, которая зависит от действия
Существуют и другие, но об этом позже в
CALLBACK
Допустимые действия описаны константами класса \Bitrix\Main\Grid\Panel\Actions
:
-
Создание элементов (
CREATE
) - добавляет новые элементы в текущую группу.DATА
- набор описаний элементов. -
Активация (
ACTIVATE
) - делает элемент доступным для взаимодействия.DATA
- идентификаторы элементов. -
Показ и сокрытие (
SHOW
/HIDE
) - скрывает/показывает элементы в группе.DATA
- идентификаторы элементов. -
Скрыть все, кроме (
HIDE_ALL_EXPECT
) - скрывает все элементы кроме перечисленных.DATA
- идентификаторы элементов. -
Показать все (
SHOW_ALL
) - показывает все элементы в группе -
Удаление (
REMOVE
) - удаляет элементы в группе.DATA
- идентификаторы элементов -
Функция-обработчик (
CALLBACK
) - выполняет произвольный javascript код
Комплексный пример
Пример работы удобно рассматривать на основе кнопки Редактирование, которая поставляется сниппетом getEditButton
(см. Сниппеты):
[
'TYPE' => 'BUTTON',
'ID' => 'grid_edit_button',
'NAME' => '',
'CLASS' => 'icon edit',
'TEXT' => 'Редактировать',
'TITLE' => 'Редактировать отмеченные элементы',
'ONCHANGE' => [
[
'ACTION' => 'CREATE',
'DATA' => [
[
"TYPE" => "BUTTON",
"ID" => "grid_save_button",
"NAME" => "",
"CLASS" => "save",
"TEXT" => "Сохранить",
"TITLE" => "",
"ONCHANGE" => [
[
"ACTION" => "SHOW_ALL",
"DATA" => [],
],
[
"ACTION" => "CALLBACK",
"DATA" => [
['JS'=>'Grid.editSelectedSave()']
],
],
[
"ACTION" => "REMOVE",
"DATA" => [
['ID'=>'grid_save_button'],
['ID'=>'grid_cancel_button'],
],
],
],
],
[
"TYPE" => "BUTTON",
"ID" => "grid_cancel_button",
"NAME" => "",
"CLASS" => "cancel",
"TEXT" => "Отменить",
"TITLE" => "",
"ONCHANGE" => [
[
"ACTION" => "SHOW_ALL",
"DATA" => [],
],
[
"ACTION" => "CALLBACK",
"DATA" => [
["JS" => "Grid.editSelectedCancel()"]
],
],
[
"ACTION" => "REMOVE",
"DATA" => [
["ID" => "grid_save_button"],
["ID" => "grid_cancel_button"],
],
],
],
]
],
],
[
'ACTION' => 'CALLBACK',
'DATA' => [
['JS' => "Grid.editSelected()"]
],
],
[
'ACTION' => 'HIDE_ALL_EXPECT',
'DATA' => [
['ID'=>'grid_save_button'],
['ID'=>'grid_cancel_button'],
],
],
],
],
Данный код описывает кнопку, которая будет активна до тех пор, пока не будет выделен хотя бы один элемент в таблице. Нажатие на кнопку спровоцирует 3 последовательных действия:
- Создание на форме 2 кнопок (Сохранить и Отменить - к ним мы еще вернемся)
- Выполнение произвольного JS кода (
Grid.editSelected()
) - Скрытие всех других элементов с формы, кроме добавленных кнопок
В свою очередь, можно заметить что метод CREATE
позволяет создавать элементы со своей логикой. Так например кнопка “Сохранить” вызывает последовательные действия:
- Показывает все доступные элементы группы
- Выполняет произвольный JS код (
Grid.editSelectedSave()
) - Удаляет элементы (себя и кнопку отменить, добавленные родительской кнопкой)
Посмотрите класс со сниппетами, чтобы найти больше интересных и разнообразных примеров.
Функция-обработчик
Самый большой интерес производит для нас выполнение собственного произвольного javascript кода, но тут все не так уж и однозначно. Во-первых, javascript код не исполняется сразу - в зависимости от настроек может быть отображен системный диалог подтверждения действия. Во-вторых, по сути это не один скрипт, а последовательность скриптов, где падение одного прервет цепочку выполнения.
В самой минимальной версии код выглядит так (пример взят из примера выше):
[
"ACTION" => \Bitrix\Main\Grid\Panel\Actions::CALLBACK,
"DATA" => [
['JS'=>'Grid.editSelectedSave()']
],
],
А полная версия может выглядеть так:
[
"ACTION" => \Bitrix\Main\Grid\Panel\Actions::CALLBACK,
"CONFIRM" => true,
"CONFIRM_MESSAGE" => "Внимательно <strong>смотрите</strong> пример?",
"CONFIRM_APPLY_BUTTON" => "Да",
"CONFIRM_CANCEL_BUTTON" => "Нет",
"DATA" => [
['JS'=>'awesomecode();'],
['JS'=>'another_awesomecode();'],
],
],
Что из себя представляют awesomecode
и another_awesomecode
?
Обычные javascript функции которые будут вызваны в глобальном контексте. В них может быть любой javascript код, в том числе код который может обращаться к гриду.
Сниппеты
Иногда, собирать вручную стандартные кнопки (Применить, Сохранить, Удалить, Отменить) и другие управляющие элементы (чек-бокс ‘Для всех’) становится довольно скучным и однообразным занятием. На такой случай в системе предусмотрен класс со сниппетами (Bitrix\Main\Grid\Panel\Snippet
), который содержит уже реализованные типовые элементы.
Пример получения типовых элементов:
use Bitrix\Main\Grid\Panel\Snippet;
$snippet = new Snippet();
$saveButton = $snippet->getSaveEditButton();
$editButton = $snippet->getEditButton();
$cancelEditButton = $snippet->getCancelEditButton();
$removeButton = $snippet->getRemoveButton();
$applyButton = $snippet->getApplyButton([
'ONCHANGE' => [] // ...
]);
$forAllCheckbox = $snippet->getForAllCheckbox();
Пример использования сформированных кнопок в группе:
[
'CLASS' => 'abcd',
'ITEMS' => [
$saveButton,
$cancelEditButton,
$editButton,
$removeButton,
$applyButton,
$forAllCheckbox,
],
],
Общее примечание: данным пример выводит все кнопки, но на самом деле многие из этих управляющих элементов содержат внутри себя определенные поведения и выводить их все не следует.
Кнопка “Сохранить” ($saveButton) - выполняет отправку данных в случае редактирования грида с указанием кода edit
, перезагружает форму
Кнопка “Отменить” ($cancelEditButton) - прерывает действие редактирование (если оно было)
Кнопка “Редактировать” ($editButton) - переводит грид в режим редактирования, фиксирует отмеченные строчки, выводит кнопки “Сохранить” и “Отменить”.
Кнопка “Удалить” ($removeButton) - выводит подтверждающее диалоговое окно и в случае подтверждения - отправляет запрос с указанием кода delete
Кнопка “Применить” ($applyButton) - выполняет действие переданное в ONCHANGE
параметре
Чек-бокс “Для всех” ($forAllCheckbox) - в случае если отмечен, в удалении или применении может быть отправлен дополнительным флагом для обработки на сервере всех записей