Требуется вставить управляющие элементы (select
+ submit
) формы в шапку ('#header'
) render-массива типа 'table'
.
Однако, поскольку ключи элементов форм, начинающиеся с символа '#', считаются свойствами объекта, build-механизм иначе обрабатывает такие элементы/вхождения (см Element::children()
).
Т.е. элементы рендерятся в нужном месте, но уже не в контексте формы. Соответственно, кнопка сабмита не работает (точнее по нажатию на неё происходит сабмит, но берётся ID и submit-callback другой (самой первой на странице формы) кнопки.
В случае с элементами форм, которые нужно вставить в ряды таблицы выход известен: использовать любой произвольный элемент, отличный от '#rows'
. Но это относится именно к рядам, а не к шапке таблицы ('#header'
).
Какие могут быть решения? Возможно даже применение JS, если это спасёт ситуацию (внимание: форма AJAX'овая, перезагружается вся таблица).
В общем, требуется какой-то workaround. Элементы нужны именно в шапке таблицы.
Пример (так не работает):
<?php
$form['orders']['rows'] = [
'#type' => 'table',
'#header' => [
...
['data'=> [
'set_status' => [
'#type' => 'select',
'#title' => 'Статус',
'#name' => 'set_status',
'#options' => $order_statuses,
],
'apply_status' => [
'#type' => 'submit',
'#value' => '!',
'#name' => 'apply_status',
'#submit' => ['::submitApplyStatus'],
],
]],
],
...
];
?>
PS. Вариант делать шапку как обычный ряд (выделяя его как шапку через кастомный CSS) - нежелателен, поскольку приведёт к другим проблемам. Да и по сути, это беспомощный выход.
Комментарии
Пока, как временный выход, за пределами таблицы добавлен скрытый select, дублирующий аналогичное поле из шапки. По клику на сабмит-кнопке в шапке на JS происходит копирование выбранного значения из оригинального селекта и осуществляется сабмит формы.
Это работает, но решение явно костыльное.
<?php
$form['mass_status'] = [
'#type' => 'select',
'#title' => 'Массовый статус',
'#options' => $order_statuses,
'#empty_option' => '- Любой -',
'#empty_value' => '_none',
'#default_value' => '_none',
'#wrapper_attributes' => ['style' => 'display: none;'],
];
...
$form['orders']['rows'] = [
'#type' => 'table',
'#header' => [
...
['data'=> [
'set_status' => [
'#type' => 'select',
'#title' => 'Статус',
'#name' => 'set_status',
'#options' => $order_statuses,
],
'apply_status' => [
'#type' => 'submit',
'#value' => '!',
'#name' => 'apply_status',
'#submit' => ['::submitApplyStatus'],
],
]],
],
...
];
?>
JS:
Drupal.behaviors.SOME_MODULE = {
attach: function (context, settings) {
$('[name="apply_status"]').once('apply-status').click(function(e) {
e.preventDefault();
var status = $('[name="set_status"]').val();
$('[name="mass_status"]').val(status);
$('form#FORM_ID').submit();
});
}
};
})(jQuery, Drupal);
В некоторых случаях костыльное решение является единственным рабочим)