D9. Элемент 'submit' в '#header' таблицы - можно ли заставить работать?

Главные вкладки

Аватар пользователя OldWarrior OldWarrior 28 июня 2021 в 17:33

Требуется вставить управляющие элементы (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) - нежелателен, поскольку приведёт к другим проблемам. Да и по сути, это беспомощный выход.

Комментарии

Аватар пользователя OldWarrior OldWarrior 28 июня 2021 в 21:10

Пока, как временный выход, за пределами таблицы добавлен скрытый 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:

(function ($, Drupal) {
  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);