[Yiibooster] [Select2]

Dear yii-collegues,

I have a form with yiibooster and a select2Row with person names (1 MB of data or 20000 records!). To avoid loading the complete data at the time of document loading (which took about 20 sec or so), I tried to load the data with the filter function of select2 via ajax (after user input):

  • form is loaded without data

  • when the user inputs some search term, the select2 widget shows only filtered records

So the action in PersonsController is:




protected function actionAllnames(){

	if(isset($_GET['q'])){

	    $queryterm  = $_GET['q'];

        $model      = new Persons;

        $persons    = Persons::model()->findAll(array(  'order'     => 'lastname', 

    	                                                'condition' => 'lastname LIKE :lastname', 

    	                                                'params'    => array(':lastname'=>$queryterm . '%')

                                                      ));

        // didn't work:

        // $data = array();

        // foreach ($persons as $person) {

        //      $data[] = array(

                            // 'id' => $person->uuid,

                            // 'text' => $person->lastname,

                            // );

        //}

        $data       = CHtml::listData($persons, 'uuid', 'lastname') ;

        echo CJSON::encode($data);

    }

	Yii::app()->end();

}



and in the view I have the select2Row:




...

<?php echo $form->select2Row($model,'person_uuid', array(   

       'asDropDownList' => false,

       'options' => array(

                       'minimumInputLength'=>'2',

                       'width'      => '348px',

                       'placeholder'=> 'Select Person',

                       'allowClear' => TRUE,

                       'ajax'       => array(

                                   'url'       => Yii::app()->controller->createUrl('persons/allnames'),

                                   'dataType'  => 'json',

                                   'data'      => 'js:function(term, page) { return {q: term }; }',

                                   'results'   => 'js:function(data) { return {results: data}; }',

                               ),

                        ),

        'id' =>'fld-personselect',

        )) ; 

 ?>

...



After input of 2 characters, for example "Te", there are no values shown, only "Searching…"

In firebug the following is shown: 500 Internal Server Error

Parameters

q Te

r persons/allnames

and there is this error :




<h1>CException</h1>

<p>PersonsController and its behaviors do not have a method or closure named "actionallnames". 

(... CInlineAction.php(49): CComponent->__call('actionallnames', Array)

...



But action is named "actionAllnames" in PersonsController and the action is also allowed:




array('allow', // allow authenticated user to perform 'create' and 'update' actions

        'actions'=>array('create','update','edit','allnames'),

		'users'=>array('@'),

    ),

array('allow', // allow admin user to perform 'admin' and 'delete' actions

		'actions'=>array('admin','delete','allnames'),

		'users'=>array('admin'),

 ... 



Maybe I’m missing something on the ajax/js side, should there be an extra

javascript? :blink: Any ideas are very wellcome … thank you in advance!

Greetings


protected function actionAllnames(){

Shouldn’t that be public?

Thanks for your quick response, Tsunami!

Of course, silly me, that was one correct part to my question. (I go home for now, because temperature is too hot in my office…!)

Now firebug complains that my data[] array is empty at select2.js (line 1248:




if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) {

render("<li class='select2-no-results'>" + opts.formatNoMatches(search.val()) + "</li>");

return;

}



The responseText is correctly formatted (json) and shown , readyState is 4, status 200 (ok), but still the select2 doesn’t show any name values. I will check and post my solution when I’ve found the rest.

But anyhow,thanks for your answer and the answers that may come…

UPDATE:

Hello yii supporters,

with my corrected controller (see **** ):




public function actionAllnames(){

    if(isset($_GET['q'])){

        $queryterm  = $_GET['q'];

        $model      = new Persons;

        $persons    = Persons::model()->findAll(array(  'order'    => 'lastname', 

                                                        'condition'=> 'lastname LIKE :lastname', 

                                                        'params'   => array(':lastname'=>$queryterm . '%')

                                                    ));

        $data       = CJSON::encode(CHtml::listData($persons, 'uuid', 'lastname')) ;  // **** changed here ***** 

        echo $data ;

    }

        Yii::app()->end();

}



… results are coming back as a correct JSON string (with no error in firebug), but results are not shown in the select2-dropdown.

I assume, maybe it has something to do with the select2 option ‘asDropDownList’ => FALSE. If I set it to TRUE, it complains that data should not be blank(?) Do I have to deliver HTML-tags around the results???

Any help is appreciated, thanks in advance!

UPDATE #2:

Now I have a working solution with the following changes in my controller action (see ****):




$data = array();

// ***** BEGIN change here

foreach ($persons as $person) {

       $data[] = array(

                       'id'   => $person->uuid,

                       'text' => $person->lastname . ', ' . $person->firstname,

                       );

            }

// this one didn't work: $data = CJSON::encode(CHtml::listData($persons, 'uuid', 'lastname')) ;

echo CJSON::encode($data) ;

// **** END of change



Happy yii-ing!

Thank you soo much Zorba! Your posts helped me a lot!

I needed to be able to show the selected model value and to get that working I added value and initSelection in the options-array:




'value'          => $model->byggnadsverk->id,

'initSelection'  => 'js:function(element, callback) 

                    { 

                        var data = {id: element.val(), text: "'.$model->byggnadsverk->byggnadsverksnummer. " - ". $model->byggnadsverk->namn.'"};

                        callback(data);

                    }',



Thanks again!

Thank you @zorbathe greek! :)

thank you very very much!!!!