i need this , i try, thanks derek
On Wed, Sep 2, 2009 at 10:23 PM, denormalized <[email protected]>wrote: > > I've spent hours trying to figure out all the pieces to the puzzle of > dependent selects. Here's my solution, in part gathered form messages on > the zend framework mailing list. > > Typical problem: A form with country and city selects. Selecting a > country > should automatically populate the city select. Pre-existing values for > country and city should automatically be shown in the form. > > > Step 1. Define a country data source. > > Country select will be based on data from a Zend_Db_Table_Abstract. I've > defined a generic "lookup table" resource which defines a getLookup method > for returning name/value pairs: > > public function getLookup($filterName = null, $filterValue = null) > { > $select = $this->select(); > if (null !== $filterName && null !== $filterValue) > { > $select->where($filterName.' = '.$filterValue); > } > $select->order($this->_order); > return $this->fetchAll($select); > } > > So when you add your options in the form: > > $country = new Community_Resource_Country(); > $countrySelect = new > Zend_Dojo_Form_Element_FilteringSelect('countryId'); > foreach ($country->getLookup() as $c) { > $countrySelect->addMultiOption($c->countryId, $c->name); > } > > > Step 2. Define a city data source which can be filtered by country ID. > > You need a way to query and return JSON-formatted data sets. Create a > specialized controller or add an action to a controller that handles this: > > public function lookupAction() > { > $filterName = $this->_request->getParam('filterName'); > $filterValue = $this->_request->getParam('filterValue'); > > // Again we're using a generic lookup table class > $_model = new Community_Resource_City(); > $data = $_model->getLookup($filterName, $filterValue); > > if (null !== $data) { > $items = array(); > foreach ($data as $row) { > $items[] = array('label' => $row->name, 'name' => $row->name, 'key' => > $row->cityId); > } > > $final = array( > 'identifier' => 'key', > 'items' => $items, > ); > echo Zend_Json_Encoder::encode($final); > } > > Because this controller or controller action doesn't need to return any > fancy stuff (layout, css, etc.), we can disable the layout and view > renderer: > > public function preDispatch() > { > // Disable for entire controller. Otherwise, put these calls into your > action function > $this->_helper->layout()->disableLayout(); > $this->_helper->viewRenderer->setNoRender(true); > } > > > Step 3. Ensure your form is dojo-enabled. > > class Myproject_Form_Member_Base extends SF_Form_Abstract > { > public function init() > { > // Dojo-enable the form: > Zend_Dojo::enableForm($this); > > > Step 4. Configure your form elements to use the data sources: > > // Country select using a lookup resource > $country = new Community_Resource_Country(); > $countrySelect = new > Zend_Dojo_Form_Element_FilteringSelect('countryId'); > $countrySelect->setLabel('Location') > ->setRequired(true); > $countrySelect->addMultiOption('', ''); > foreach ($country->getLookup() as $c) { > $countrySelect->addMultiOption($c->countryId, $c->name); > } > // IMPORTANT: Whenever the country is changed, the data store > // for the dependent city select should also change > $countrySelect->setAttrib('onchange', 'dijit.byId("cityId").store = new > dojo.data.ItemFileReadStore({ url: > "/data/lookup/table/city/filterName/countryId/filterValue/" + > dijit.byId("countryId").value });'); > $this->addElement($countrySelect); > > > $city = new Community_Resource_City(); > $citySelect = new Zend_Dojo_Form_Element_FilteringSelect('cityId'); > $citySelect->setAutocomplete(true); > $citySelect->setLabel('City'); > $citySelect->setRequired(true); > $citySelect->setStoreId('city'); > $citySelect->setStoreType('dojo.data.ItemFileReadStore'); // important! > $this->addElement($citySelect); > > > Step 5. Pre-populate the city select with data. > > At this point the city select won't be populated until the country select > is > changed. But what if we already know the initial country ID? Zend_Form > won't automatically populate the city select for us! > > Therefore, in the controller of our action, after we create the form we > need > to programmatically populate the city select: > > // set the dojo city lookup based on country id > $countryId = $this->_getParam('countryId',false); > // Note that for my project, id's can never be 0, so I can use the > empty function > if (!empty($countryId)) { > // memberForm is a reference to the form we will display > > $this->view->memberForm->getElement('cityId')->setStoreParams(array('url' > => > > '/data/lookup/table/city/filterName/countryId/filterValue/'.$memberValues['countryId'])); > $this->view->defaultCityId = $countryId; > } > > > Step 6. Set the value of the city select. What if we already have a value > for city? (For instance, a user is editing his profile, which already has > a > city value.) > > Unfortunately, simply calling $citySelect->setValue($cityId) won't work! > (This is currently a bug listed in Zend.) This may be due to the fact that > the city FilteringSelect has not yet been populated with data. > > So, we need some way to set the value of the select AFTER it has been > populated. > > In our controller, set a variable in the view with the value of our > country: > > $this->view->defaultCityId = $this->_getParam('cityId',false); > > In our view script that shows the form: > > <?=$this->memberForm ?> > > <? if (!empty($this->defaultCityId)) : ?> > <script type="text/javascript"> > dojo.addOnLoad(function() { > dijit.byId('cityId').attr('value','<?=$this->defaultCityId; ?>'); > }); > </script> > <? endif; ?> > > Note that I put this script AFTER I output the form. Why? Zend will > automatically output a dojo.addOnLoad which loads your city select > ItemFileReadStore. You cannot set the value of your select BEFORE the > ItemFileReadStore is loaded, so we need to set the city value later. > > Check the source of your page in the browser. Make sure you set the value > of your city select AFTER the dojo.addOnLoad which loads your > ItemFileReadStore. > > > Now your form should not only have dependent selects, but also pre-populate > the city select correctly. > > Derek > > > -- > View this message in context: > http://www.nabble.com/How-to%3A--Zend-Dojo-Form-Dependent-Selects-%28e.g.-Country-City%29-tp25269984p25269984.html > Sent from the Zend Framework mailing list archive at Nabble.com. > >
