-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Changing form repopulation behaviour
I have noticed many posts about the repopulation of selects, checkboxes and radios. In particular, the repopulation of multiple select items and using the set_select() method does not work without defining it in the form_validation->set_rules().
This article deals with the repopulation of mulitple select values. It relates to the library form_validation and the helper form_helper and the methods set_select() and form_dropdown().
Reference example code:
# controller : register
// load helper/library
$this->load->library('form_validation');
$this->load->helper('form_helper');
// set validation rules
$this->form_validation->set_rules('fullname','Full Name','required');
// ... other rules
// check form validation
if ($this->form_validation->run())
{ // valid info. process and redirect.
redirect('success');
}
else
{ // Do one of two things.
// 1. Populate the form for the first time.
// 2. Re-populate the form (invalid form data).
$this->load->view('my_form');
}
# view : my_form
// ... other view info. (form action is 'register')
<input type="text" name="fullname" value="" />
<select name="interests[]" mutiple="multiple">
<option value="chess" <?php echo set_select('interests[]','chess');?> >Chess</option>
<option value="food" <?php echo set_select('interests[]','food');?> >Food</option>
<option value="php" <?php echo set_select('interests[]','php');?> >PHP!</option>
</select>
// ... other view info
Frequently encountered problems:
- form_dropdown() cannot be used with set_select() and therefore values will always be re-populated with default data.
- If the select item is not defined in the form validation rules repopulation does not occur. The fix is to add a 'dummy' rule (if it is not required).
$this->form_validation->set_rule('interests[]','Interests','');
- The behaviour for set_select() and repopulation is set to repopulate the values with initial default values if the validation is incorrect. An example would be if we set the default for "food" to be selected. If the user selects "chess" and submits the form and the form is not valid then the value of "food" is used to repopulate the form when the user has selected "chess".
In short it is difficult to create a solution without having to write a custom helper or callback function to validate multiple selects. This is especially true if the list of values are dynamically created or is very long - since each option must be declared and repopulated manually.
Solution The solution to all of the above problems is to use the form_dropdown() function and modify it to manually check the $_POST for selected values. This can easilly be achieved by using a MY_form_helper and overriding the form_dropdown() method.
You can also preserve the original function and use a prefix my_form_dropdown() if you do not want to preserve the CI core code.
The solution is described below: [quote]
- Create a file in your application/helpers directory called MY_form_helper.
- Copy the form_dropdown() function in the form_helper file (system/helpers).
- Look for the following two lines of code.
# Inside your application/helpers/MY_form_helper : form_dropdown()
// .....
$multiple = (count($selected) > 1 && strpos($extra, 'multiple') === FALSE)//...
//------> Insert code here (corresponds to Line 307 in original form_helper.php)
$form = '<select name="'.$name.'"'.$extra.$multiple.">\n"; //....
// .....
- Insert the following code.
# Insert the following code
//-------------------------
// Check post if post is not empty
if (! empty($_POST))
{ // Post data exists. Default is select has no options selected.
$selected = array();
// Strip the [] from the name if multiple
$post_name = preg_replace('/\[\]/','',$name);
// Check for value(s) for this select item by name in $_POST array
if (isset($_POST[$post_name]))
{ // Check if multiple values
if (is_array($_POST[$post_name]))
{ // Extract each posted item
foreach ($_POST[$post_name] as $posted)
{ // Override default values with posted values
$selected[] = $posted;
}
}
else
{ // Single select value
$selected = array($_POST[$post_name]);
}
}
}
The post values for the select will override the default values which is how the user expects the form to behave (repopulate the form with their selected values). If you prefer to override to the default values you can use the original method.
Notes
- Compatible with the form validation class
- No need to set dummy validation rule for optional selects.
- Minimal modifications, no hacks and no extra methods needed
- Works with optgroups.
Example Usage: In the reference example above, the following could be used.
$options = array('chess'=>'Chess','food'=>'Food','php'=>'PHP!');
$defaults = array('food'); // I want to set to 'food' for the example
// Example, i want to set food as the default value
echo form_dropdown('interests[]',$options,$defaults,'multiple="multiple"');
// OR
echo form_multiselect('interests[]',$options,$defaults);
[/quote]
It may be possible to extend this approach for the checkboxes but at the moment I have not investigated this idea. Also it may not be the most elegant solution but from my testing so far it seems to work very well.