如何将模型数据加载到在 Yii 中使用 Ajax 过滤的 Select2 下拉列表

Posted

技术标签:

【中文标题】如何将模型数据加载到在 Yii 中使用 Ajax 过滤的 Select2 下拉列表【英文标题】:How to load model data to Select2 dropdown which uses Ajax filtering in Yii 【发布时间】:2014-05-23 06:30:31 【问题描述】:

我在视图中使用以下 select2 Yii 小部件来填充下拉列表。由于准备选择列表所需的数据包含超过 2K 条记录,我使用 select2 和 minimumInputLength 参数和一个 ajax 查询来根据用户输入生成列表的部分结果。如果我创建一个新记录,我完全没有问题。它可以很好地填充所有内容,我可以将数据保存到我的数据库中。但是,我不知道如何在更新操作期间将保存的数据加载回此下拉列表。我在某处读到了 initselection 用于此目的,但我不知道如何使用它。

有人可以帮我解决这个问题吗?

我的看法:

$this->widget('ext.select2.ESelect2', array(
            'selector' => '#EtelOsszerendeles_osszetevo_id',
            'options'  => array(
                    'allowClear'=>true,
                    'placeholder'=>'Kérem válasszon összetevőt!',
                    'minimumInputLength' => 3,
                    'ajax' => array(
                            'url' => Yii::app()->createUrl('etelOsszerendeles/filterOsszetevo'),
                            'dataType' => 'json',
                            'quietMillis'=> 100,
                            'data' => 'js: function(text,page) 
                                            return 
                                                q: text,
                                                page_limit: 10,
                                                page: page,
                                            ;
                                        ',
                            'results'=>'js:function(data,page)  var more = (page * 10) < data.total; return results: data, more:more ; ',
                    ),
            ),
          ));?>

我的控制器的动作过滤器:

public function actionFilterOsszetevo()

    $list = EtelOsszetevo::model()->findAll('nev like :osszetevo_neve',array(':osszetevo_neve'=>"%".$_GET['q']."%"));
    $result = array();
    foreach ($list as $item)
        $result[] = array(
                'id'=>$item->id,
                'text'=>$item->nev,
        );
    
    echo CJSON::encode($result);

【问题讨论】:

【参考方案1】:

我使用 initSelection 以这种方式加载现有记录以进行更新(我将您的一些视图代码替换为 ... 以专注于主要更改)。用 Yii 1.1.14 测试。本质上,我使用了两种不同的 ajax 调用:

查看:

<?php

$this->widget('ext.select2.ESelect2', array(
        'selector' => '#EtelOsszerendeles_osszetevo_id',
        'options'  => array(
                ...
                ...
                'ajax' => array(
                        'url' => Yii::app()->createUrl('client/searchByQuery'),
                        ...
                        ...
                        'data' => 'js: function(text,page) 
                                        return 
                                            q: text,
                                            ...
                                        ;
                                    ',
                        ...
                ),
                'initSelection'=>'js:function(element,callback) 
                   var id=$(element).val(); // read #selector value
                   if ( id !== "" ) 
                     $.ajax("'.Yii::app()->createUrl('client/searchById').'", 
                       data:  id: id ,
                       dataType: "json"
                     ).done(function(data,textStatus, jqXHR)  callback(data[0]); );
                   
                ',
        ),
      ));
?>

现在在您的控制器中,您应该收到用于 ajax 处理的参数:查询 (q),作为字符串,插入时; id (id) 更新时为 int。在 $_GET 中读取时,参数名称必须与 ajax data 参数相同(在此示例中插入 q;在更新中 id)。代码未重构/优化:

控制器:

 public function actionSearchByQuery()
        $data = Client::model()->searchByQuery( (string)$_GET['q'] );
        $result = array();
        foreach($data as $item):
           $result[] = array(
               'id'   => $item->id,
               'text' => $item->name,
           );
        endforeach;
        header('Content-type: application/json');
        echo CJSON::encode( $result );
        Yii::app()->end(); 
 

 public function actionSearchById()
        $data = Client::model()->findByPk( (int) $_GET['id'] );
        $result = array();
        foreach($data as $item):
           $result[] = array(
               'id'   => $item->id,
               'text' => $item->name,
           );
        endforeach;
        header('Content-type: application/json');
        echo CJSON::encode( $result );
        Yii::app()->end(); 
 

模型 - 自定义查询和一点秩序/安全/干净:)

 public function searchByQuery( $query='' ) 
        $criteria = new CDbCriteria;
        $criteria->select    = 'id, ssn, full_name';
        $criteria->condition = "ssn LIKE :ssn OR full_name LIKE :full_name";
        $criteria->params = array (
            ':ssn' => '%'. $query .'%',
            ':full_name' => '%'. $query .'%',
        );
        $criteria->limit = 10;
        return $this->findAll( $criteria );
 

编辑:

当使用传统的 HTTP Post(同步,例如 Yii 生成的表单)预加载更新时,它可以开箱即用。对于异步/Ajax 更新,例如使用 JQuery:

事件/触发器:

$('#button').on("click", function(e) 
        ...  
        ... your update logic, ajax request, read values, etc
        ...
        $('#select2_element').select2('val', id_to_load );
);

这样,initSelection 将再次以异步方式运行,并使用新的 id_to_load 值,按 id 重新加载记录。

根据您的情况和您的需要,initSelection 可能完全不同,以避免来自 db 或 you can use formatResult and formatSelection custom functions (are described in Load Remote Data sample source code) 的加载记录。阅读文档,我知道 initSelection 的回调需要带有 id 和文本元素的 JSON 数据才能正确加载,或者您可以尝试将这两个概念结合起来(此 initSelection 与您的自定义 JS 事件/触发器调用)(未测试):

       'initSelection'=>'js:function(element,callback) 
                   // here your code to load and build your values,
                   // this is very basic sample 
                   var id='myId'; 
                   var text='myValue'; 
                   data = 
                     "id": id,
                     "text": text
                   
                   callback(data);                       
        ',

或者直接在触发调用上:

$('#button').on("click", function(e) 
        ...  
        ...             ...
        $("#select2_element").select2("data", id: "myId", text: "MyVal");
);

希望对您有所帮助。

【讨论】:

谢谢亚历杭德罗!我会试一试,很快就会回复你。 我正在玩这个,但我需要对 initSelection 部分进行一些解释。实际上,我的 initSelection 过滤器操作从 url 中获取所有必需的信息,因此我不必向它传递任何数据。我认为这是您代码的第一部分在 initSelection 中所做的。因此,一旦我按下更新按钮并开始更新操作,过滤器控制器就可以返回选定的 id 和值。那么,如何将它传递给我的 select2 小部件以用作初始值? @g0m3z 您好,请查看编辑部分,希望对您有所帮助 感谢您抽出宝贵时间帮助我!我根据您的宝贵意见解决了这个问题,这有助于我了解 initSelection 的工作原理。我在第一次尝试时做错的是我在 ajax 定义中包含了initSelection。在我将它移到适当的位置后,它工作正常。一旦调用更新操作,我使用以下代码加载值:initSelection'=&gt;'js:function(element,callback)var data=id:'.$model-&gt;osszetevo-&gt;id.',text:"'.$model-&gt;osszetevo-&gt;nev.'"; callback(data);',【参考方案2】:

我试过这样做,但做不到

我想出的填写和选择记录的解决方案是:

如果属性有一些数据(在更新模式或默认值),我写了一些 javascript 在文档就绪事件之后,将用我的数据填充选择(只需选择它并在其中推送 html),并制作它选择了,然后我休息(或更新)选择以显示我的工作。

【讨论】:

以上是关于如何将模型数据加载到在 Yii 中使用 Ajax 过滤的 Select2 下拉列表的主要内容,如果未能解决你的问题,请参考以下文章

Yii2 - 使用 Ajax 加载为 Select2 插件设置值

Yii: 如何在CGridView通过Ajax方式刷新数据后执行JS脚本

Yii - ajax 加载的表单元素的用户端验证

Yii 客户端验证不适用于 ajax 加载的表单

Yii2 - 在模型中提交时如何从小部件中获取数据?

如何将Yii2模型作为数组?