A Smarter Select Tag for HTML Forms

by Castwide on 8-24-2007 • Tags: code, pagemill, php0 comments

One of the often repeated tasks I've noticed in web development is the need to write logic for selecting an option in a select element. In a form for users to edit their billing address, for example, there could be a drop-down for the state, and the user's current state should be the default option. The common solution is to add boilerplate code to the routine that populates the select element. This is a typical example in PHP:

<select name="state">
<? foreach ($states as $s) { ?>
<option value="<?= $s ?>"<? if ($user['state'] == $s)
echo ' selected="selected"'; ?>><?= $s; ?></option>
<? } ?>
</select>

It does the job, but I think it's an annoying piece of code to repeat every time for such a simple problem. As Ron Popeil's sidekick says in the infomercials, "There's got to be a better way!"

Enter the PHP Pagemill. This template engine provides the ability to create custom tags that can be transformed into HTML. My goal was to use this feature to create a new select tag with a "selected" attribute. The template code (using hardcoded states as a crude example) would look like this:

<pm:select name="state" selected="OH">
<option value="AK">AK</option>
<option value="AL">AL</option>
<option value="AR">AR</option>
<option value="AZ">AZ</option>
<option value="CA">CA</option>
<!--// etc. -->
<option value="OH">OH</option>
<!--// etc. -->
</pm:select>

Instead of adding logic to every option, you only need to declare the selected value in the pm:select tag. The Pagemill would turn it into a standard select tag and add the selected attribute to the option with the declared value.

The function that implements the tag took about as long to write as it would normally take me to write the logic for a select element the old-fashioned way several times over, and now I have a custom tag that handles the dirty work every time. Here's the function:

<?
function selectTag($innerHTML, $attribs) {
$selected = '';
$attribtext = '';
foreach ($attribs as $k => $v) {
if ($k == 'selected') {
$selected = $v;
} else {
$attribtext .= " {$k}=\"{$v}\"";
}
}
if ($selected != '') {
$opts = Pagemill::buildPageArray($innerHTML, array('option'), false);
foreach ($opts as $o) {
if ($o->attributes['value'] == $selected) {
$newCode = str_replace('outerXml);
$innerHTML = str_replace($o->outerXml, $newCode, $innerHTML);
break;
}
}
}
return "<select{$attribtext}>\n{$innerHTML}\n</select>";
}
?>

Let's take a look at a simple example that enables the tag. We'll put the above function in a file called select.tag.php and include the two required files at the top of the script.

<?
require_once('pagemill.class.php');
require_once('select.tag.php');
?>

Now we need to declare a Pagemill object and enable the select tag.

<?
$pm = new Pagemill();
$pm->registerTag('pm:select', 'selectTag');
?>

This example will simply take the selected option in a submitted form, echo it back to the user, and automatically select the option in the drop-down box. Here's the code for the rest of the script:

<?
if ($_REQUEST['state']) {
$pm->setVariable('state', $_REQUEST['state']);
}
$pm->addLoop('states', array('state' => 'AK'));
$pm->addLoop('states', array('state' => 'AL'));
$pm->addLoop('states', array('state' => 'AR'));
$pm->addLoop('states', array('state' => 'AZ'));
$pm->addLoop('states', array('state' => 'CA'));
// List of states has been truncated for simplicity's sake

echo $pm->writeFile('select.tmpl');
?>

Here's the select.tmpl template:

<html>
<head>
<title>Smart Select</title>
</head>
<body>
<condition name="state">
<p>
Your currently selected state is @{state}@.
</p>
<else />
<p>
You have not selected a state.
</p>
</condition>
<form>
<pm:select name="state" selected="@{state}@">
<option value=""></option>
<loop name="states">
<option value="@{state}@">@{state}@</option>
</loop>
</pm:select>
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

In a robust and well-designed application, The pm:select tag should simply become an available feature in all your templates.

This smart select tag will be an integrated feature of the next version of Phrameworks.

Try the example

Download the code

There are no comments posted to this news item.

Add Comment

More Articles