1

I have created a form with an embedded table for inputs, where one of the table columns contains a select field; the rest are textfields. The textfields all work fine, but the rendering of cells with the select field fails to create any <input> tag in its rendering. So naturally the form fails to act on any changes the user makes to this field.

In the following snippet, I have omitted a lot of data pre-processing. To give some context, I have created a $result array that has 4 or 5 rows of node data. Some of that get extracted to other variables to form the defaults for each form item.

This is the form.

function mymodule_walker_registration_form($form, &$form_state) {
  $form['table'] = array(
    '#theme' => 'mymodule_form_table',
    '#header' => array(
      array('data' => t('Walker\'s name'), 'class' => array('col-c3')), 
      array('data' => t('Date of birth'), 'class' => array('col-c4')), 
      array('data' => t('Age range'), 'class' => array('col-c5')),
    ),
    'rows' => array(
      '#tree' => TRUE,
    ),
  );

  foreach ($result as $walker_nid) {
    // a bit of data processing omitted: exctract various variables for use as defaults
    $form['table']['rows'][$row_number] = array(
      // Text field for the walker name
      'c3' => array(
        '#type' => 'textfield',
        '#default_value' => $walker_name,
        '#size' => 32,
        '#maxlength' => 32,
        '#required' => TRUE,
      ),
      // Text field for the walker date of birth
      'c4' => array(
        '#type' => 'date_text',
        '#default_value' => $walker_dob,
        '#date_format' => 'j/n/Y',
        '#required' => FALSE,
      ),
      // Select field for the walker age type ('scout', 'explorer', 'adult')
      'c5' => array(
        '#type' => 'select',
        '#title' => 'Walker age range',
        '#options' => drupal_map_assoc($age_ranges), 
        '#default_value' => $walker_age,
        '#required' => TRUE,
      ),
    );
  }

  // The submit buttons  
  // The 'Register team' button
  $form['e80progress_register'] = array(
    '#type' => 'submit',
    '#title' => t('Register team'),
    '#value' => t('Register walkers (get walker numbers)'),
    '#submit' => array('e80progress_team_registration_register'),
  );

  // The 'cancel' button
  $form['e80progress_cancel'] = array(
    '#type' => 'submit',
    '#value' => t('Cancel'),
    '#attributes' => array('onclick' => 'if(!confirm("You will lose any changes.  Are you sure you want to cancel?")){return false;}'),
    '#submit' => array('e80progress_team_registration_cancel'),
    '#limit_validation_errors' => array(),
  );

  return $form;
}

The hook_theme() implementation is nothing special.

function mymodule_theme() {
  return array(
    'mymodule_form_table' => array(
      // The renderable element is the form.
      'render element' => 'form',
    ),
  );
}

The issue comes in processing the table. I know that the select element gets this far.

function theme_mymodule_form_table(&$variables) {
  // Get the useful values.
  $form = $variables['form'];
  $rows = $form['rows'];
  $header = $form['#header'];

  // Setup the structure to be rendered and returned.
  $content = array(
    'header' => $header,
    'rows' => array(),
  );

  // Traverse each row.  @see element_chidren().
  foreach (element_children($rows) as $row_index) {
    $row = array();
    // Traverse each column in the row.  @see element_children().
    foreach (element_children($rows[$row_index]) as $col_index) {
      // Render the column form element.
      $row[] = array('data' => drupal_render($rows[$row_index][$col_index]), 'class' => array("col-$col_index"));
    }
    // Add the row to the table.
    $content['rows'][] = $row;
  } 

  // Theme the table and return.
  return theme('table', $content);
}

The only element that does not render correctly is the select cell. Visually, it is perfect. Functionally, it omits the <input> tag. This is how that cell renders:

<div class="form-item form-type-select form-item-rows-r1-c5"> 
  <label for="edit-rows-r1-c5">Walker age range 
    <span class="form-required" title="This field is required."></span>
  </label> 
  <select id="edit-rows-r1-c5" name="rows[r1][c5]" class="form-select required">
    <option value="Scout 12 years or older" selected="selected">Scout 12 years or older</option>
    <option value="Explorer">Explorer</option>
    <option value="Network">Network</option>
    <option value="Adult with DBS">Adult with DBS</option>
  </select>
</div>

How do I make drupal_render() or some other function to include the <input> tag into that cell of the table?

3
  • sorry why are you bothering to put the whole form into a themed html table ?! Does the whole form render fine in a node or simple menu path page when calling drupal_get_form('walker_registration_form');? Eg, outside of a table ... If it looks ok, then look to your theme function, if it looks broken, then look to your form function for errors.
    – tenken
    Feb 3 '18 at 0:02
  • The form is called from a simple menu item using (drupal_get_form('walker_registration_form') as you state. I want the table since it is the most logical presentation to use: compact and visually easy to use. The form renders visually, but leave out that one set of input tags. I probably could do it without using a table and using CSS to arrange in a table-like fashion, but a table struck me as the easiest way (I'm not sure that this is answering your question).
    – user13167
    Feb 3 '18 at 13:50
  • OK - I have been stupid and had forgotten my html syntax. The select tag does not have an input tag as part of it. My problem is elsewhere in my drupal project, but not in the rendering of the form.
    – user13167
    Feb 6 '18 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.