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

时间:2022-11-27 18:31:57

I use the following select2 Yii widget in my view to populate a drop-down list. Since the data necessary for the preparation of the select list consists of more than 2K records I use select2 with minimumInputLength parameter and an ajax query to generate partial result of the list based on user input. If I create a new record I have no problem at all. It populates everything fine and I can save data to my database. However I don't know how to load saved data back to this drop-down during my update action. I read somewhere that initselection intended for this purpose but I couldn't figure out how to use it.

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

Can someone help me out on this?

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

My view:

$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 }; }',
                    ),
            ),
          ));?>

My controller's action filter:

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

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);
}

2 个解决方案

#1


4  

I use initSelection to load existing record for update in this way (I replaced some of your view code with ... to focus in main changes). Tested with Yii 1.1.14. Essentially, I use two different ajax calls:

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

View:

<?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]); });
                   }
                }',
        ),
      ));
?>

Now in your controller you should receive parameters for ajax processing: query (q), as string, when inserting; id (id) as int when updating. Parameter names must be same as ajax data parameters (in this sample insert q; in update id) when read in $_GET. Code is not refactored/optimized:

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

Controller:

 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(); 
 }

Model - custom query and a little of order / security / clean :)

模型 - 自定义查询和一点订单/安全/清洁:)

 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 );
 }

EDIT:

It works out of box when update is preloaded with traditional HTTP Post (synchronous, for example with Yii generated forms). For async/Ajax updates, for example with JQuery:

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

Event / Trigger:

事件/触发器:

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

With this, initSelection will run again in async way with new id_to_load value, reloading record by id.

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

In your case and for your needs, initSelection could be complete different to avoid load record from db or you can use formatResult and formatSelection custom functions (are described in Load Remote Data sample source code). Reading documentation, I understand that initSelection's callback need JSON data with id and text elements to load properly or you could try to combine both concepts (this initSelection with your custom JS event/trigger call) (not tested):

在您的情况下并且根据您的需要,initSelection可以完全不同以避免来自db的加载记录,或者您可以使用formatResult和formatSelection自定义函数(在加载远程数据示例源代码中描述)。阅读文档,我理解initSelection的回调需要带有id和text元素的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);                       
        }',

Or directly on Trigger call:

或直接在Trigger调用:

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

Hope that helps.

希望有所帮助。

#2


0  

I tried doing that way, but couldn't do it

我试着这样做,但是做不到

the solution I came up to get my record filled and selected was:

我得到的记录填写和选择的解决方案是:

In case of the attribute having some data(in update mode or default value), I wrote some javascript that after document ready event, would fill the select with my data (just selected it ind pushed html in it), and made it selected, and then I rest( or update) the select to show my work.

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

#1


4  

I use initSelection to load existing record for update in this way (I replaced some of your view code with ... to focus in main changes). Tested with Yii 1.1.14. Essentially, I use two different ajax calls:

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

View:

<?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]); });
                   }
                }',
        ),
      ));
?>

Now in your controller you should receive parameters for ajax processing: query (q), as string, when inserting; id (id) as int when updating. Parameter names must be same as ajax data parameters (in this sample insert q; in update id) when read in $_GET. Code is not refactored/optimized:

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

Controller:

 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(); 
 }

Model - custom query and a little of order / security / clean :)

模型 - 自定义查询和一点订单/安全/清洁:)

 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 );
 }

EDIT:

It works out of box when update is preloaded with traditional HTTP Post (synchronous, for example with Yii generated forms). For async/Ajax updates, for example with JQuery:

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

Event / Trigger:

事件/触发器:

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

With this, initSelection will run again in async way with new id_to_load value, reloading record by id.

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

In your case and for your needs, initSelection could be complete different to avoid load record from db or you can use formatResult and formatSelection custom functions (are described in Load Remote Data sample source code). Reading documentation, I understand that initSelection's callback need JSON data with id and text elements to load properly or you could try to combine both concepts (this initSelection with your custom JS event/trigger call) (not tested):

在您的情况下并且根据您的需要,initSelection可以完全不同以避免来自db的加载记录,或者您可以使用formatResult和formatSelection自定义函数(在加载远程数据示例源代码中描述)。阅读文档,我理解initSelection的回调需要带有id和text元素的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);                       
        }',

Or directly on Trigger call:

或直接在Trigger调用:

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

Hope that helps.

希望有所帮助。

#2


0  

I tried doing that way, but couldn't do it

我试着这样做,但是做不到

the solution I came up to get my record filled and selected was:

我得到的记录填写和选择的解决方案是:

In case of the attribute having some data(in update mode or default value), I wrote some javascript that after document ready event, would fill the select with my data (just selected it ind pushed html in it), and made it selected, and then I rest( or update) the select to show my work.

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