Symfony forms question (restoring selected value of a dynamically populated sfWidgetFormSelect widget)
I am using Symfony 1.3.2 with Propel ORM on Ubuntu 9.10.
I have developed a form that dynamically populates a select widget with cities in a selected country, using AJAX.
Before the data entered on the form is saved, I validate the form. If validation fails, the form is presented back to the user for correction. However, because the country list is dynamically generated, the form that is presented for correction does not have a valid city selected (it is empty, since the country widget has not changed yet).
This is inconvenient for t开发者_如何学Che user, because it means they have to select ANOTHER country (so the change event is fired), and then change back to the original country they selected, then FINALLY select the city which they had last selected.
All of this is forced on the user because another (possibly unrelated) field did not vaildate.
I tried $form->getValue('widget_name'), called immediately after $form->bind(), but it seems (infact, IIRC, if form fails to validate, all the values are reset to null) - so that does not work.
I am currently trying a nasty hack which involves the use of directly accesing the input (i.e. tainted) data via $_POST, and setting them into a flash variable - but I feel its a very nasty hack)
What I'm trying to do is a common use case scenario - is there a better way to do this, than hacking around with $_POST etc?
What I do for this exact issue is that I post the form to the same action that generated it, and in that action, I grab any selected countries/regions/cities as POST variables and pass them back to the template (regardless of validation). In the template, I then use JQuery to set the select values to what they were. When validation passes, they get used. When not, they get passed back to template.
If you can tolerate a little PHP in your JQuery, you could do this in the template:
$(document).ready(function()
{
$("#country-select").val('<?php echo $posted_country; ?>');
});
If you use this approach, don't forget to initialise $this->posted_country in your template the first time around or Jquery will get confused.
I guess you could also use $this->form->setWidget(...)->setDefault(...) or something similar, but I havent found a way around using $_POST as accessing the elements seems to need binding the form otherwise.
UPDATED CODE IN RESPONSE TO COMMENTS BELOW:
if($_POST['profile']['country_id'] != '')
{
$this->posted_country = $_POST['profile']['country_id'];
$q = Doctrine_Query::create()
->select('c.city_id, c.city_name')
->from('City c')
->where('c.country_id = ?', $this->posted_country);
$cities = $q->execute(array(), Doctrine_Core::HYDRATE_NONE);
foreach($cities as $city) $list[$city[0]] = $city[1];
$this->form->setWidget('city_id', new sfWidgetFormChoice(array('choices' => array('' => 'Please select') + $list)));
}
So... I get the country from the post, I query db with that, get cities, and craft cities back into a dropdown. Then in the template, you can set a default selected city with something like $this->posted_city (which would be a POST variable too, if exists).
精彩评论