Development

Dynamic and AJAX-driven Select Lists in Webform

multiple-webform-submit

This example is a two-for-one deal! I’m going to demonstrate how to

  1. dynamically populate a webform select list on page load
  2. dynamically populate a webform select list based upon the value chosen in another webform select list

For both parts of this example, the demo form I’ll be using is a “Get Started” form.

Part 1

This is actually quite simple given that Webform has the appropriate hooks to do this. We’re going to be using the hook_webform_select_options_info() hook. You can read about this at http://drupal.org/node/406486. In this example, to populate the “Select a Campus Location” select list we want to query the database for all published location nodes (location​ is the name of the Campus Locations content type). To populate the “Select a Program” select list, we’ll be doing a similar thing for the initial page load, but we’ll also be re-populating this list after the user chooses a campus location. The specification for the form called for the two select lists to be optional. So, initially, we want the user to be able to pick any program or campus location, but if the user chooses a campus location, we need to then limit the programs list to programs related to this location. The relationship is achieved through a multi-select node reference field within program that points to one or more ​locations​.

Here’s how we use the aforementioned hook_webform_select_options_info() for each of these fields.

After saving this code, we can browse to the settings page for each of the fields. The additional options show up under the Load a pre-built option listsetting. We can now set each of them accordingly. Once set, when the form is viewed, the callback functions will be used to populate the two select lists.

The webform now has dynamic “Select a Campus Location” and “Select a Program” dropdowns. I should note that I used jQuery to change the initial values of these fields. By default, they had an initial selected option of “– None –

Part 2

Now that we have the options we’d like in each of the two select lists, let’s take care of the AJAX piece. Admittedly there are probably cleaner, more efficient ways of adding this functionality, but I’ll let you choose if this method is for you or not.

In a nutshell what we’re going to do is look for changes to the “Select a Campus Location” select list. Once the user changes the value, we need to use AJAX to ask Drupal for the available programs at the chosen location. The callback function will pass back to jQuery the new select list options as a single string of HTML. This is the part where there may be a better way to do this. Once jQuery gets the results back from Drupal, we’ll just replace all of the select options with the new ones.

The first step is to create a menu item that will handle our AJAX request.

Next, we need to create the callback function itself. Note that we’ll be passing the node ID of the chosen location as an argument/parameter.

Lastly, we need to write some jQuery code to look for the select list change, grab the associated programs, and modify the program select list. I put this into my script.js file, but you may choose to make a separate javascript file for this. If so, this is demonstrated at the end of the tutorial athttp://viziontech.co.il/tutorial1.

Note that we’re using a GET request here. There are some good tutorials on using POST instead. Here is one of my favorites: http://viziontech.co.il/tutorial1

Conclusion

There are undoubtedly many different ways to achieve the same behavior, so please explore the alternatives. You may also want to implement some sort of error handling on the AJAX callback to make sure something useful happens if there is a problem. It’s been a long day, so I’m going to wrap this up. Thanks for reading!

3 Comments

    • adam

      Nicholas, there’s no reason you couldn’t do that. You’d just have to change the queries a bit. Without knowing your specific needs, that’s all I can really say about it. Cheers!

  • Paul

    Great write up!

    I know this is an old post but hope someone can help out. I have the same exact needs as you had (dynamically populate a webform select list based upon the value chosen in another webform select list) except my data is stored in a mysql dbase table – and not as nodes. For Part 1 I have the following code:

    function exhibitors_webform_select_options_info() {
    $items[‘company’] = array(
    ‘title’ => ‘Company’,
    ‘options callback’ => ‘exhibitors_get_company_for_select_list’,
    );
    $items[‘booth’] = array(
    ‘title’ => ‘Booth’,
    ‘options callback’ => ‘exhibitors_get_booth_for_select_list’,
    );
    return $items;
    }

    function exhibitors_get_company_for_select_list() {
    $options = array();
    $sql = “SELECT company FROM {exhibitors} ORDER BY company”;

    $result = db_query($sql);
    foreach ($result as $row) {
    $options[$row->company] = $row->company;
    }
    return $options;
    }

    function exhibitors_get_booth_for_select_list() {
    $options = array();
    $sql = “SELECT booth FROM {exhibitors} ORDER BY company”;

    $result = db_query($sql);
    foreach ($result as $row) {
    $options[$row->booth] = $row->booth;
    }
    return $options;
    }

    Above works perfectly. I have my 2 Select Lists available in Webform.

    What I would like to do is when a user chooses a Company on the drop down the Booth field populates with the corresponding number that is on the same row as the company under the booth column.

    Where I am stuck is the call back function. Your example is using the node id as the paramater/argument but since I am not using nodes am not sure how to go about doing this.

    Any help is appreciated.

    Thanks!

Leave a Reply to nicholas Cancel reply

Your email address will not be published.