【转】Yii在表单中建立关联下拉列表dropdown

转自:

    应用中经常遇到需要在表单form中使用两个关联的下拉列表dropdown。其中一个下拉列表中的数据依赖于另一个下拉列表的当前值。例如填写地 址,当 我们修改’国家’下拉列表的值,’城市’列表中的项目就会全部更新为该国的城市。通过Yii内建的AJAX功能可以比较容易的实现关联下拉列表的功能。下 面简要介绍实现过程。

    首先,在表单的view文件中,我们需要在表单中显示国家和依赖于国家的城市两个下拉列表。
 
echo CHtml::dropDownList('country_id','', array(1=>'USA',2=>'France',3=>'Japan'),
    array(
        'ajax' => array(
        'type'=>'POST', //url请求类型
        'url'=>CController::createUrl('currentController/dynamiccities'), //要调用的url.
        //Style: CController::createUrl('currentController/methodToCall')
        'update'=>'#city_id', //ajax请求要更新的目的元素,这里是城市下拉列表
        //'data'=>'js:javascript statement'
        //这里不设置data,默认将传递当前表单form中的所有元素数据
    )));
 
//此处数据为空,因需要根据其他下拉列表的值来更新
echo CHtml::dropDownList('city_id','', array());

    简单起见,在这里第一个’国家’的下拉列表由一系列 键值/文本 数组构成,当然我们也可以简单修改,使其从数据库中读取,并使用CHtml::listData处理成这种key/value数组。

    在上面的表单中,一旦它的值发生变化,都会触发一个ajax请求,发送给当前控制器controller的 ‘dynamiccities’动作。请求的结果( ‘dynamiccities’动作的输出)将被更新到第二个下拉列表的值(id是city_id)。
    接下来,要修改控制器controller代码,添加’dynamiccities’的动作响应,输出将用来填充‘城市’下拉列表的html。在这里,他需要根据请求的国家代码country_id输出相应的城市列表:
public function actionDynamiccities()
{
    $data=Location::model()->findAll('parent_id=:parent_id',
                  array(':parent_id'=>(int) $_POST['country_id']));
    $data=CHtml::listData($data,'id','name');
    foreach($data as $value=>$name)
    {
        echo CHtml::tag('option',
                   array('value'=>$value),CHtml::encode($name),true);
    }
}
    这里Location是用来储存城市信 息的AR模型,关联的国家代码字段为parent_id。CHtml::listData将搜索到的数据对象(object)转换为 [key]:value形式的数组,key为属性id的值,value为属性name的值。然后,以tag的形式逐一输出,供第二个下拉列表(城市 dropdown)更新数据。
    你可能会奇怪_POST['country_id']参数是哪里来的?其实,当ajax参数数组中‘data’内容为空时(请查看第一个国家列表的ajax设置),ajax会将下拉列表所在表单的所有元素值都通过ajax请求传递给控制器。
    想修改也可以。默认情况下,ajax参数数组中的’data’设置为 js:jQuery(this).parents(“form”).serialize() 。前缀js告诉Yii:接下来将是一个javascript语句。所以,如果你想要改变’data’参数的值,你可以加入自己的javascript语 句,并使用js:开头。上述方法对于’success’参数也适用。
还需要修改控制器的规则,给新添加的动作分配适当的权限。例如我们可以把
array('allow', // allow authenticated user to perform 'create' and 'update' actions
                'actions'=>array('create','update'),
                'users'=>array('@'),
            ),

修改为

array('allow', // allow authenticated user to perform 'create' and 'update' actions
                'actions'=>array('create','update','dynamiccities'),
                'users'=>array('@'),
            ),
小贴士:出于测试目的我们还可以在filters方法中注释掉下面这句:
'accessControl', // perform access control for CRUD operations
 
这将禁用所有的访问权限控制。测试完成后,别忘了启用它。

 

 
posted on 2012-12-26 19:40  风在竹林  阅读(597)  评论(0编辑  收藏  举报