Hello all

I'd like to ask if there is a way to modify dynamically the options of a select form item according to the selection made on another select form item. These options are retrieved from a table in the database.
I am not familiar to jquery (less to ajax), could anyone suggest me an idea for this ?

Thanks

Comments

mcantelon’s picture

Here's some JQuery code I've used to do this. In my example when a section select is changed, a category select will be populated with options looked up via AJAX. So when the select with the ID "edit-gstimeout_admin_add-categorize-section" is changed, an AJAX request is made to "/ajax/categories" for the child categories within the section. The select with the ID "edit-gstimeout_admin_add-categorize-category" is then populated with the resulting JSON data.

Note that, in my example, there is a DIV wrapper around the category selector that allows the select element to be faded out then in (and hidden when it's empty).

JQ(function() {
  if (!(JQ("select#edit-gstimeout_admin_add-categorize-category").attr('length') > 1)) {
    JQ("div#gstimeout_category_select_wrapper").fadeOut('fast');
  }
  JQ("select#edit-gstimeout_admin_add-categorize-section").change(function() {
    JQ.getJSON("/ajax/categories",{section_id: JQ("select#edit-gstimeout_admin_add-categorize-section").val()}, function(j){
      var options = '';
      for (var i = 0; i < j.length; i++) {
        options += '<option value="' + j[i].optionValue + '">' + j[i].optionDisplay + '</option>';
      }
      if (i == 1) {
        JQ("div#gstimeout_category_select_wrapper").fadeOut('fast');
      } else {
        JQ("div#gstimeout_category_select_wrapper").fadeIn('fast');
      }
      if (navigator.appName == 'Microsoft Internet Explorer') {
        // We do things this way, instead of just changing innerHTML, because IE7 has innerHTML/select bug
        var start_select = '<select name="edit[gstimeout_admin_add][categorize][category]" class="form-select" id="edit-gstimeout_admin_add-categorize-category" >';
        var end_select = '</select>';
        var new_tag = start_select + options + end_select;
        JQ("select#edit-gstimeout_admin_add-categorize-category").attr('outerHTML', new_tag);
      } else {
        JQ("select#edit-gstimeout_admin_add-categorize-category").html(options);
      }
    })
  })
})

Hope this helps.

JQuery stuff is fun, but a bit mind-bending when you first get into it. :)

-Mike Cantelon
http://mikecantelon.com

mooffie’s picture

Here's some JQuery code I've used to do this.

BTW, doesn't Drupal complain "an illegal choice has been detected..." when you submit this form? AFAIK, it's supposed to complain, because the user selects some <OPTION> which wasn't seen by drupal_get_form et al. You can circumvent this by doing '#DANGEROUS_SKIP_CHECK' => TRUE on the form element (alternatively, it can be defined as a textfield).

because IE7 has innerHTML/select bug

Uff :(

But you don't need to do HTML stuff in your code. You could go along the lines of:

var options = $.map(j, function(item) {
  $(document.createElement('option')).val(item.optValue).html(item.optDiaply);
});
...
$('#the-select').empty().append(options);
mcantelon’s picture

BTW, doesn't Drupal complain "an illegal choice has been detected..." when you submit this form?

For whatever reason I haven't ran into that.

But you don't need to do HTML stuff in your code. You could go along the lines of:

Definitely cleaner... Thanks!

-Mike Cantelon
http://mikecantelon.com