Easy chained select lists using Zend Framework and Prototype

Building a set of select lists that are dependant of each other can be a daunting task, but for a simple two-level list – in that what you select from one drop-down will changing what’s displayed in one or more other drop-downs – is actually quite easy thanks to Zend Frameworks and Prototype, both of which support Json.


What I needed to do was have a list of items. Each item would have a different type, colours, range and so on. When I selected an item from a select list I wanted the other optional lists to update. Now, I’ve seen this done with Ajax to completely rebuild the html of the select lists, but I didn’t want to go down that route. Instead, I decided to use a bit of PHP and a bit of Javascript.

First of all I had to decide how I wanted to store my items. I could have gone down the headache of a database, but I wanted to keep this simple. So in steps the always-simply ini file. Zend Framework makes it really easy to parse this particular format, which is great news!

The ini file looks something like:

[_default]

name   = "_default"
type   = ""
range  = "home; garden; garage; kitchen"
colour = "white; silver; black; red; blue; yellow; green"

[fridge : _default]

name   = "Fridges and freezers"
type   = "double; chest; mini"

[fork : _default]

name   = "Forks"
type   = "big; small"
range  = "kitchen; garden"
colour = "silver; black"

[trash : _default]

name   = "Trash cans"

As you can see, I extend one base item type, changing only what I need to.

Now I have my ini file, I need to convert that to Json. The easiest way to do this is simply to load the whole ini file into a nicely formatted array and convert that array to the Json format. The PHP to do that is actually quite simple, and looks something like this:

<?php

require 'Zend/Config/Ini.php';
require 'Zend/Json.php';

$config = new Zend_Config_Ini(dirname(__FILE__) . '/items.ini', null);

$items = array();
foreach ($config as $key => $val) {
    if ($key{0} != '_') {
        foreach ($val as $k => $v) {
            $items[$key][$k] = (strstr($v, ';')) ? array_map('trim', explode(';', $v)) : $v;
        }
    }
}
$json = Zend_Json::encode($items);

Again, the Zend Framework comes to the rescue and does all the hard work for me. All I have to do is process the ini file, making arrays out of lists (the strings separated with semi-colons) and ignoring anything that starts with an underscore.

That file ends up giving me a Json string and a PHP array, both of which can be used in the form. In this HTML I have quickly put in the select lists, but I’m sure you could do something programmatically, or in a template, or something… this is just for show, after all. 😉

<?php include('json.php'); ?>
<html>
<head>
    <script type="text/javascript" src="prototype.js"></script>
    <script type="text/javascript">
        var items = '<?php echo $json; ?>'.evalJSON(true);
        var optlist = ['type', 'range', 'colour'];

        Event.observe(window, 'load', function() {
            Event.observe('item', 'change', function() {
                var itype = $F('item');
                optlist.each(function(o) {
                    $(o).options.length = 1;
                    if (itype) {
                        if (items[itype][o].length > 0) {
                            for (i = 0; i < items&#91;itype&#93;&#91;o&#93;.length; i++) {
                                $(o).options&#91;$(o).options.length&#93; = new Option(items&#91;itype&#93;&#91;o&#93;&#91;i&#93;);
                            }
                            $(o).enable();
                        } else {
                            $(o).disable();
                        }
                    } else {
                        $(o).disable();
                    }
                });
            });
        });

    </script>
</head>
<body>

<form action="" method="post">

Item<br />
<select name="item" id="item">
<option value="">Select an item</option>
<?php

    foreach ($items as $type => $details) {
        echo '<option value="', $type, '">', $details['name'], "</option>\n";
    }

?>
</select><br />

Type<br />
<select name="type" id="type" disabled="disabled">
    <option value="">Please select</option>
</select><br />

Range<br />
<select name="range" id="range" disabled="disabled">
    <option value="">Please select</option>
</select><br />

Colour<br />
<select name="colour" id="colour" disabled="disabled">
    <option value="">Please select</option>
</select><br />

<p><input type="submit" /></p>

</form>

</body>
</html>

The main part of that is, of course, the javascript. Using Prototype I’m easily able to convert the Json string from the PHP file back in to an object, and then set an event observer on the items select list to register a change in value. All that’s left to do is loop over the other form elements (which, to make things easy, I hard-coded in to the optlist variable, but again, this could be dynamic) and set the correct values, enabling or disabling the form elements where needed.

The above code can be found running at:

http://dev.amnuts.com/chained/

Did you like this? Share it:

One thought on “Easy chained select lists using Zend Framework and Prototype

  1. Hi Everyone,

    Could u help me how to do Easy Chained select lists using Zend Framework and Oracle .

    I need exactly like when u select object from first drop down list it will automatically populate second drop down list with data as parent to child relationship using oracle Database.

    Could u please sort out my problem .

    Thanks Everyone

    Warm regards
    Muzeeb

Leave a Reply