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

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