Por que meu formulário tem como tabela não postando dados corretamente ou exibindo corretamente?

10

Eu criei um formulário no administrador.

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

Em seguida, adiciono cada linha a ele como:

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),
);

}

O formulário está ótimo! Mas o primeiro problema é o valor atribuído #default_valuenão está aparecendo no formulário. Quando eu mudo para #valueo valor correto aparece. Então, eu me pergunto como isso deve ser feito. A documentação do Drupal diz #valueque não deve ser usada com formulários, embora esteja funcionando exatamente como eu esperaria que funcionasse.

O principal problema é quando preencho alguns dados de teste em um dos campos de texto e os envio: Não vejo nenhum dos valores enviados em minha _submitfunção.

Nem $formnem $form_statecontém qualquer um dos valores introduzidos I nos campos de texto.

Gostaria de saber se isso é porque estou processando #theme => "table"? Alguém já encontrou esse problema? Alguma idéia de alterações que eu possa fazer que me permita ver os valores que estou inserindo ao publicar o formulário na _submitfunção?

dm03514
fonte

Respostas:

13

O problema é que seus elementos de campo de texto estão localizados sob a #rowspropriedade de sua matriz de renderização.

Drupal vê qualquer chave de matriz começando #como uma propriedade / atributo, e qualquer chave de matriz que não comece com isso como um elemento que precisa ser atendido recursivamente. Assim, os filhos que você tem #rowssão ignorados pelo criador de formulários.

Como theme_tableserá executado na matriz de renderização, os elementos do formulário serão renderizados na tela, mas o formulário não terá nenhum conhecimento dos valores (pois eles não são tecnicamente filhos do formulário).

Na minha experiência, a melhor maneira de fazer esse tipo de coisa é usar uma função de tema específica no elemento:

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));
}

Em sua função de formulário, você usaria código como o seguinte

$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)
  );
}

Depois disso, seus campos de texto deverão ser registrados no formulário e você poderá ver o valor na $form_statematriz normalmente.

Clive
fonte
Obrigado pela sua resposta útil. 1 consulta: como limitar meus 1000 resultados em uma única página a 50 resultados em uma página e um pager para a próxima página? Estou tendo problemas para processar o tema ('pager') com isso.
Himanshu Pathak