Yii 1.1: cascadedropdown

Easy creating of dependent dropdownlists
20 followers

This simple to use extension uses the jQuery plugin jquery-cascade to populate the data of a dependent dropdownlist by a ajax/getJSON-call.

It works with the standard CHtml::activeDropDownList or the CHtml/CActiveForm::dropDownList - no extra dropdown-components needed.

Requirements

Developed with Yii 1.1.11, not tested with other releases

Usage

Extract the zip-file into your to protected/extensions directory. Import the component in config/main.php

// autoloading model and component classes
'import'=>array(
    'application.models.*',
    'application.components.*',
......
    'ext.cascadedropdown.ECascadeDropDown',

or use

Yii::import('ext.cascadedropdown.ECascadeDropDown');

in your controller instead.

A) Two activeDropDownLists

Assume you have a model where you want to set the province and the city. But the city dropdown options depend on the selected province.

Your view

Create your dropdownlists like you would do without this extension and add a line of code to make them "cascade". It's important to assign a unique id in the htmlOptions of the dropdownlists.

...
 
//add the province dropdownlist
$provinceItems = CHtml::listData(Province::model()->findAll(), 'id', 'name');
echo CHtml::activeDropDownList($model, 'province', $provinceItems, array('id'=>'id_province','prompt'=>'-'));   
 
//add the cities dropdownlist, show only the items of the current province
$cityItems = CHtml::listData(City::model()->findAll('province=:province', array(':province'=>model->province)), 'id', 'name');  
echo CHtml::activeDropDownList($model, 'city', $cityItems, array('id'=>'id_city','prompt'=>'-'));   
 
 
//----------- the additional part ------------------------------------
//Build the dependency/cascade with province as master
//Show the text 'Loading cities ...' on waiting for the data.
//Update the city-data through the ajax-url: Yii::app()->createUrl('site/citydata')
ECascadeDropDown::master('id_province')->setDependent('id_city',array('dependentLoadingLabel'=>'Loading cities ...'),'site/citydata');  
 
...

A change of the province-dropdownlist will lead to a ajax-call to populate the corresponding cities. So you have to create the action 'citydata' in the controller 'site'. In this function you can use some static ECascadeDropDown helper method to generate the json-data response. See the sourcecode for details.

Your controller

class SiteController extends Controller
{
 
 public function actionCitydata()
 {
   //check if isAjaxRequest and the needed GET params are set 
   ECascadeDropDown::checkValidRequest();
 
   //load the cities for the current province id (=ECascadeDropDown::submittedKeyValue())
    $data = City::model()->findAll('province=:province', array(':province'=>ECascadeDropDown::submittedKeyValue());
 
   //Convert the data by using 
   //CHtml::listData, prepare the JSON-Response and Yii::app()->end 
   ECascadeDropDown::renderListData($data,'id', 'name');
 }

That should be all ... Take a look at the comments in the source for more options.

B) Three dropDownLists

If you want you can cascade three (or more) dropdownlists. Below is a ready to use example you can copy/paste for testing. It shows more ECascadeDropDown helper functions and uses the same controlleraction for all data-requests. If you want so, you have to set the controllerRoute in the master() method instead of the setDependent() method. But in most cases I would prefer to use extra controlleractions for each dropdownlist.

Your view

Combine 3 dropdownlists:

$items = array('mobile'=>'Mobile','printers'=>'Printers');
    echo CHtml::dropDownList('id_type','', $items, array('prompt'=>'-'));
    echo CHtml::dropDownList('id_company', '', array());
    echo CHtml::dropDownList('id_article', '', array());
 
    //handle all data response in one controller action
    ECascadeDropDown::master('id_type','site/selectarticle') //'controllerId/actionId'
                      ->setDependent('id_company') //master for id_article with default options
                      ->setDependent('id_article', //with custom labels
                                      array('dependentStartingLabel'=>'Select article','dependentLoadingLabel'=>'Loading articles...'));

Your action in the SiteController

public function actionSelectArticle()
{
ECascadeDropDown::checkValidRequest();  //comment to debug this url in the browser
 
$data = array(
    'id_type' => array(
        'mobile' => array('company_apple'=>'Apple','company_samsung'=>'Samsung'),
        'printers' => array('company_hp'=>'HP','company_brother'=>'Brother'),
    ),
 
    'id_company' => array(
        'company_apple' => array('imac'=>'iMac','iphone'=>'iPhone','ipad'=>'iPad','ipod'=>'iPod'),
        'company_samsung' => array('galaxy'=>'Galaxy','wave'=>'Wave'),
        'company_hp' => array('laserjet'=>'Laserjet','photosmart'=>'Photosmart'),
        'company_brother' => array('hlserie'=>'HL Serie','mwserie'=>'MW Serie'),
    )
);
 
$masterId = ECascadeDropDown::submittedMasterId();  //master dropdownlist id_type or id_company
$masterKey = ECascadeDropDown::submittedKeyValue(); //the current key of the master
//$dependentId = ECascadeDropDown::submittedDependentId(); if you need the dependent id
 
if(isset($data[$masterId][$masterKey]))
    ECascadeDropDown::renderArrayData($data[$masterId][$masterKey]); //with Yii::app()->end()
 
 
ECascadeDropDown::renderEmptyData('-');
}

Resources

Total 6 comments

#15858 report it
Joblo at 2013/12/23 04:47am
checkboxlist

This extension uses jquery-cascade, which is implemented for dropdownlists only.

#15783 report it
smarc at 2013/12/16 10:41pm
and with activeCheckBoxList ?

Thanks for this extension! It works great!

Now I would like to do a little different form. Is it possible to use this extension with an activeCheckBoxList (in which datas depend of the first dropdownlist) ?

Thanks for any ideas

#14068 report it
freshyiiuser at 2013/07/16 05:38pm
i got an empty result

i tried the three dropdownlist option, in _form.php:

<?php
        echo CHtml::dropDownList('CycleID','', CHtml::listData(Usersectionsecurity::model()->findAll(), 'Group_Code', 'E_Group_Desc'),
                array(
                        'prompt'=>'Select Cycle',
                        ));             
        echo CHtml::dropDownList('stclass', '', array());
        echo $form->dropDownList($model,'periodID', array());
 
        ECascadeDropDown::master('CycleID','Usersectionsecurity/getClassByCycle') //'controllerId/actionId'
                          ->setDependent('stclass') //master for id_article with default options
                          ->setDependent('periodID', //with custom labels
                                                          array('dependentStartingLabel'=>'Select Classes','dependentLoadingLabel'=>'Loading articles...'));
 
?>

in my controller:

public function actionGetClassByCycle()
        {
                ECascadeDropDown::checkValidRequest(); 
 
                $type = Yii::app()->user->getType();
                $userID = Yii::app()->user->getID();
 
                if($type == 'Teacher'){
                        $model = Stclass::model()->GetClassOfUser($userID, ECascadeDropDown::submittedKeyValue());
                }else{
                        $model=Usersectionsecurity::model()->findAll('Group_Code=\'' . ECascadeDropDown::submittedKeyValue() . '\''); 
                }
 
                $models=Matiere::model()->GetMainSubjectByCycle(ECascadeDropDown::submittedKeyValue());
 
                $data = array(
                        'CycleID' => CHtml::listData($model,'Class_Code', 'E_Class_Desc')
 
                        ,
 
                        'stclass' => CHtml::listData($models,'Subject_Code', 'E_Subject_Name')
 
                );
 
                $masterId = ECascadeDropDown::submittedMasterId();  //master dropdownlist id_type or id_company
                $masterKey = ECascadeDropDown::submittedKeyValue(); //the current key of the master
                //$dependentId = ECascadeDropDown::submittedDependentId(); //if you need the dependent id
 
 
                if(isset($data[$masterId][$masterKey]))
                        ECascadeDropDown::renderArrayData($data[$masterId][$masterKey]); //with Yii::app()->end()
 
 
                ECascadeDropDown::renderEmptyData('-');
        }

i made a var_dump($data), i get values but they not appears in the appropriate dr

array(2) {
  ["CycleID"]=>
  array(3) {
    [24]=>
    string(7) "Grade 4"
    [25]=>
    string(7) "Grade 5"
    [26]=>
    string(7) "Grade 6"
  }
  ["stclass"]=>
  array(10) {
    ["020"]=>
    string(28) "French as a Foreign Language"
    ["040"]=>
    string(4) "Math"
    ["061"]=>
    string(9) "Geography"
    ["062"]=>
    string(7) "History"
    ["070"]=>
    string(16) "Cultural Studies"
    ["080"]=>
    string(6) "Civics"
    ["090"]=>
    string(18) "Physical Education"
    [110]=>
    string(3) "Art"
    [120]=>
    string(5) "Drama"
    [130]=>
    string(5) "Music"
  }
}
[{"value":"","label":"-"}]

where is my error. please help me

#12409 report it
Daniel at 2013/03/18 10:49pm
cascade dropdown in TbModal

Hi,

I am using yii bootstrap extension and trying to put the dropdown on a TbModal. How could I do that? I followed the tutorial, but not success yet.

Please help...

#10276 report it
tpandi at 2012/10/17 06:29am
Usage

How to store this method used dropdownlist selected value in my current model

#10048 report it
Pedrosas at 2012/10/02 02:08am
Error

It lacks a closing parenthesis
$data = City::model()->findAll('province=:province', array(':province'=>ECascadeDropDown::submittedKeyValue());

fixed

$data = City::model()->findAll('province=:province', array(':province'=>ECascadeDropDown::submittedKeyValue()));

Leave a comment

Please to leave your comment.

Create extension