Hello,

I'm trying to set the default value for a select form element created programatically but whatever I try fails. What is the proper method for setting the default selected option for a select when using drupal_render()?

Here's a simplified version of the code (I want 'two' selected by default):

$form['my_select'] = array(
  '#type' => 'select',
  '#default_value' => 1,
  '#options' => array(
    0 => t('one'),
    1 => t('two'),
    2 => t('three'),
    3 => t('four'),
  )
);

drupal_render($form['my_select']);

I've also tried the following for #default_value:

  • array(1)
  • array(1=>'two')
  • array(1=>t('two'))
  • two
  • array(two)

Looking further I found that the function form_select_options() in the forms API completely ignores #default_value (although it is passed) when adding select="select" to the option. It does however read in #value, and if I replace #default_value with #value it renders correctly, however the formsapi documentation specifically says not to use this for what I'm trying to do - http://api.drupal.org/api/file/developer/topics/forms_api_reference.html... .

Here's the function that renders the options
From includes/form.inc

function form_select_options($element, $choices = NULL) {
  if (!isset($choices)) {
    $choices = $element['#options'];
  }
  // array_key_exists() accommodates the rare event where $element['#value'] is NULL.
  // isset() fails in this situation.
  $value_valid = isset($element['#value']) || array_key_exists('#value', $element);
  $value_is_array = is_array($element['#value']);
  $options = '';
  foreach ($choices as $key => $choice) {
    if (is_array($choice)) {
      $options .= '<optgroup label="'. $key .'">';
      $options .= form_select_options($element, $choice);
      $options .= '</optgroup>';
    }
    elseif (is_object($choice)) {
      $options .= form_select_options($element, $choice->option);
    }
    else {
      $key = (string)$key;
      if ($value_valid && (!$value_is_array && (string)$element['#value'] === $key || ($value_is_array && in_array($key, $element['#value'])))) {
        $selected = ' selected="selected"';
      }
      else {
        $selected = '';
      }
      $options .= '<option value="'. check_plain($key) .'"'. $selected .'>'. check_plain($choice) .'</option>';
    }
  }
  return $options;
}

Thanks,
Jeff

Comments

yuriy.babenko’s picture

Jeff, your simplified version of the code looks correct and should be working properly. Instead of refreshing the page, try just clicking the url and pressing ENTER. (ie. reload without the reload).

Browsers save some form information and display it again on page reload (F5). It could very well be that your #default_value was previously not working, the browser saved the value at key 0, you fixed the problem and refreshed using F5, the browser remembers your old choice and loads that up. I've fallen for this numerous times myself.
---
Yuriy Babenko
www.yubastudios.com
My Drupal tutorials: http://yubastudios.com/blog/tag/tutorials

---
Yuriy Babenko | Technical Consultant & Senior Developer
http://yuriybabenko.com

jrigby’s picture

Thanks for the suggestion Yuriy.

I've actually turned off the cache with the same results and if I look at the source code none of the options have the selected attribute.

Jeff

yuriy.babenko’s picture

Maybe it has to do with how you're rendering the form...

Try this:


function my_form()
{
$form = array();
$form['my_select'] = array(
  '#title' => t('test select'),
  '#type' => 'select',
  '#default_value' => 1,
  '#options' => array(
    0 => t('one'),
    1 => t('two'),
    2 => t('three'),
    3 => t('four'),
  )
);
return $form;
}

and then somewhere (let's say page.tpl.php for simplicity's sake):

print drupal_get_form('my_form');

---
Yuriy Babenko
www.yubastudios.com
My Drupal tutorials: http://yubastudios.com/blog/tag/tutorials

---
Yuriy Babenko | Technical Consultant & Senior Developer
http://yuriybabenko.com

jrigby’s picture

I actually can't render the complete form as I am dynamically loading these elements in an existing form. This would cause nested form elements.

nevets’s picture

Something to check, look at the generated HTML. What does the html for the select look like, in particular the option tag for what should be the default item?

jrigby’s picture

It does not add the selected attribute.

najibx’s picture

How can I used the selected list to be kept selected such as this via Onchange Jump Menu?
http://drupal.org/node/91924

Currently : '#default_value' => '',

No effect if I change default_value to this?

'#default_value' => '$term->name',

nevets’s picture

This '#default_value' => '$term->name',<.code> should be <code>'#default_value' => $term->name, (No single quotes around $term->name).

najibx’s picture

Thanks, but it's still no luck. nevets, I have seen some of your posts in other thread, I see u are very good at Form API !

Does the onChange, might caused this? Possibly onchange does not recognise default_value ? I read somewhere regarding

'#attributes' => array(
'onChange' => "self.location.href=document.getElementById('$formname').options[document.getElementById('$formname').selectedIndex].value"),
);

I did clear cache, run update, with no succes either.

How about form_select_options() ? Would this be helpful?

Greatly thanks ~

nevets’s picture

Looking at the code again you want $term->tid (the value returned, not what is shown), But I wonder if $term->tid even has a value, once you leave the while loop $term is not even set.

najibx’s picture

The actual value of pulldownlist is as below.

<option value="/management-news/101">Vol. MN08-05 2008 May 21</option>
$term->tid does have a value, but the actual value I am looking for is "management-news/101" which is $term->name?

    while ($term = db_fetch_object($vocabulary)) {
     $options[url("management-news/$term->tid")] = $term->name;
    }

I also tried :

'#default_value' => 'management-news/$term->tid',
'#default_value' => management-news/$term->tid,

nevets’s picture

Try double quotes around the value (instead of single quotes). And I need to stop reading so fast, complete value would be url("management-news/$term->tid") (in general the index to $options)

najibx’s picture

Not so sure what you mean there ..
but i tried

'#default_value' => url("management-news/$term->tid"),
'#default_value' => "management-news/$term->tid",

In addition to this, I got another problem. When one of the nodes is selected, the respective volume number (in the pulldownlist) must be selected too. Is there other way to work around this ... How about form_select_options() ?

nevets’s picture

Ok, here is a complete working example (It uses the last term found as the default)

<?php
$output = drupal_get_form('Company_dropdown_form', $form);
return $output;

function Company_dropdown_form() {
    $vid=1;
    $formname="Company";
  
    $vocabulary = db_query("SELECT td.name, td.tid FROM {term_data} td WHERE td.vid=%d ORDER BY td.name", $vid);
    // Initialise the country array
    $options[] = t('List by ' . $formname);
    //Populate array with url / name
    while ($term = db_fetch_object($vocabulary)) {
      $options[url("taxonomy/term/$term->tid")] = $term->name;
      $last = url("taxonomy/term/$term->tid");
    }
    //Build dropdown select
    //If we try to build OnChange directly it gets mangled, so put in array to confuse the forms api
    $form['category'] = array(
      '#type' => 'select',
      '#name' => $formname,
      '#id' => $formname,
      '#title' => '',
      '#default_value' => $last,
      '#options' => $options,
      '#description' => '',
      '#multiple' => $multiple = FALSE,
      '#required' => $required = FALSE,
      '#attributes' => array('onChange' => "top.location.href=document.getElementById('$formname').options[document.getElementById('$formname').selectedIndex].value"),
    );
        return $form;
}
?>