質問

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.

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);
}
役に立ちましたか?

解決

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:

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:

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:

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.

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'=>'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:

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

Hope that helps.

他のヒント

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.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top