Im using Zend_Dojo_Data and in a controller for my datasource but it still
can't filter, Im sure having issues with the onchange
'dojo.data.ItemFileReadStore ' url. Is possible to break the onchange url
down me, that only seems to be the problem now. Thanks



denormalized 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://old.nabble.com/How-to%3A--Zend-Dojo-Form-Dependent-Selects-%28e.g.-Country-City%29-tp25269984p26266681.html
Sent from the Zend Framework mailing list archive at Nabble.com.

Reply via email to