Почему моя форма в виде таблицы неправильно публикует данные или отображает их неправильно?

10

Я создал форму в админке.

$form['things'] = array(
  '#prefix' => '<div id="things">',
  '#suffix' => '</div>',
  '#tree' => TRUE,
  '#theme' => 'table',
  '#header' => array(t('Field Label'), t('Field Name'), t('Location'), t('Stuff')),
  '#rows' => array(),
);

Затем я добавляю каждую строку к нему как:

foreach ($type_fields as $field_name => $attrs) {
  $stuff = array(
    '#type' => 'textfield',
    '#default_value' => $attrs['stuff'],
  );

$form['things']['#rows'][] = array(
  array('data' => 'label'),
  array('data' => $field_name),
  array('data' => $field_name),
  array('data' => $stuff),
);

}

Форма выглядит великолепно! Но первая проблема заключается в том, что присвоенное значение #default_valueне отображается в форме. Когда я изменяю его #valueна правильное значение, появляется. Вот интересно, как это сделать? Документация Drupal говорит, #valueчто не следует использовать с формами, хотя она функционирует именно так, как я ожидаю, что она будет работать.

Основная проблема - когда я заполняю некоторые тестовые данные в одном из текстовых полей и отправляю их: я не вижу ни одного из переданных значений в моей _submitфункции.

Ни содержит, $formни $form_stateсодержит значения, которые я ввожу в текстовые поля.

Интересно, это потому что я рендеринг #theme => "table"? Кто-нибудь сталкивался с этой проблемой? Любые идеи об изменениях, которые я могу сделать, которые позволили бы мне видеть значения, которые я ввожу, когда я отправляю форму в _submitфункцию?

dm03514
источник

Ответы:

13

Проблема в том, что ваши элементы текстового #rowsполя расположены под свойством вашего массива рендеринга.

Drupal рассматривает любой ключ массива, начинающийся с, #как свойство / атрибут, а любой ключ массива, не начинающийся с этого, как элемент, который необходимо рекурсивно использовать. Как таковые дети, под которыми вы находитесь, #rowsбудут игнорироваться конструктором форм.

Поскольку он theme_tableбудет работать в массиве рендеринга, ваши элементы формы будут фактически отображены на экране, но форма не будет иметь никаких знаний о значениях (поскольку они не являются технически дочерними элементами формы).

По моему опыту, лучший способ сделать это - использовать определенную функцию темы для элемента:

function MYMODULE_theme() {
  return array(
    'MYMODULE_textfield_table' => array(
      'render element' => 'element'
    )
  );
}

function theme_MYMODULE_textfield_table($vars) {
  $element = $vars['element'];

  $rows = array();
  foreach (element_children($element) as $key) {
    $rows[] = array(
      array('data' => 'label'),
      array('data' => $element[$key]['#extra_data']['field_name']),
      array('data' => $element[$key]['#extra_data']['field_name']),
      array('data' => render($element[$key]))
    );
  }

  $header = array(t('Field Label'), t('Field Name'), t('Location'), t('Stuff'));
  return theme('table', array('header' => $header, 'rows' => $rows));
}

Тогда в вашей функции формы вы будете использовать код, подобный следующему

$form['things'] = array(
  '#prefix' => '<div id="things">',
  '#suffix' => '</div>',
  '#tree' => TRUE,
  '#theme' => 'MYMODULE_textfield_table'
);

foreach ($type_fields as $field_name => $attrs) {
  $form['things'][] = array(
    '#type' => 'textfield',
    '#default_value' => $attrs['stuff'],
    '#extra_data' => array('field_name' => $field_name)
  );
}

После этого ваши текстовые поля должны быть зарегистрированы в форме, и вы сможете увидеть значение в $form_stateмассиве как обычно.

Клайв
источник
Спасибо за ваш полезный ответ. 1 запрос: Как ограничить мои 1000 результатов на одной странице 50 результатами на странице и пейджером для следующей страницы? У меня проблемы с рендерингом темы ('pager') с этим.
Химаншу Патхак