views:

533

answers:

2

I have code using QuickForm that creates a select widget with the following:

$form->addElement( 'select', 'state_id', 'State:', statesArray() );

statesArray() queries the database to get the states available and returns an associative array with the ids linked to the state names. I'm using a similar technique throughout the solution.

What I'd like to do is prepend this array with two options that are disabled, so that by default the select menu says something like "Please select a state" followed by a dash, both of which are disabled. If I weren't using QuickForm, the select would have the following as the first two options:

  <option value="" disabled="disabled">Select a State</option>
  <option value="" disabled="disabled">-</option>

Both options are disabled, and if the user leaves the option on the first value, the select widget submits an empty value which is made invalid by the form checking code.

Is there a way to do this with QuickForm?

Thanks, Chuck

A: 

Techinically, the best solution would be to use optgroup, but browsers usually won't default to this value, but instead to the first option in the select group.

Why not have your Select State have a value of "None" (similar to your given old-school solution) and have leave it enabled, then have the widget return the form as invalid if they leave it blank? Is this outside of the scope of QuickForm?

I think most users don't notice if something is enabled or disabled, and the only benefit of disabling is to make it un-selectable.

Is your goal geared toward validating the input? If so, why not just add some javascript between the form and QuickForm to check if the user has selected a disabled (or value="Null") element before submitting it?

Obviously I need to read the QuickForm documentation to get the full picture, but based on what I can get from your example, you could just add Please Choose State => None to the state_array and then have whatever form validator you plan to use not accept "None" as a valid input.

Anthony
That may be the workaround. Thanks. I'm also checking into the Zend Framework, as that might be a better solution for me.
Chuck
A: 

OK, after digging much deeper into the QuickForm documentation, I figured this out. The solution is to not populate the select widget with an array, but to build the select element manually add this to the form.

Originally, I had this:

function dbArray( $tableName, $fieldName ) {
    $query = <<< EOT
SELECT   `id`, `$fieldName`
FROM     `$tableName`
ORDER BY `$fieldName`
EOT;

    $link = connectToDatabase();
    $result = mysql_query( $query, $link );
    while ( $rec = mysql_fetch_assoc( $result ) );
    {
        $array[$rec['id']] = $rec[$fieldName];
    }

    return $array;
}

function statesArray() {
    return dbArray( 'states', 'name' );
}

$form = new HTML_QuickForm( 'account', 'POST' );
$form->addElement( 'select', 'state_id', 'State:', statesArray() );

I did a version where array( 'none' => 'Please select a State' ) was prepended to the dbArray call before returning the array to the calling code, but this didn't make the option disabled. Adding a rule to confirm that the choice is numeric was the workaround ($form->addRule( 'state_id', 'You must select a state.', 'numeric' )). But I still didn't like that it was selectable. Here's the solution I found.

function statesSelect() {
    $select = HTML_QuickForm::createElement( 'select' );
    $select->addOption( 'Select a State', '', array( 'disabled' => 'disabled' ) );
    $select->addOption( '-', '', array( 'disabled' => 'disabled' ) );

    $statesArray = dbArray( 'states', 'name' );
    foreach ( $statesArray as $id => $name ) {
        $select->addOption( $name, $id );
    }

    return $select;
}

$form = new HTML_QuickForm( 'account', 'POST' );
$form->addElement( statesSelect() );
$form->addRule( 'state_id', 'You must select a state.', 'required' );

I hope this helps someone else. :)

Chuck