Yii 1.1: A simple action for CJuiAutoComplete

20 followers

Scenario

More or less I use auto-complete field for a form. CJuiAutoComplete is a yii widget for this purposes. The common use case is to make an ajax request and retrieve a list from the database. So in this case you have to write a controller action to return you a json encoded list. What if I had a generic action to do this work for me?

Implementation

This is a class that extends CAction to do the work for me.

<?php
class EAutoCompleteAction extends CAction
{
    public $model;
    public $attribute;
    private $results = array();
 
    public function run()
    {
        if(isset($this->model) && isset($this->attribute)) {
            $criteria = new CDbCriteria();
            $criteria->compare($this->attribute, $_GET['term'], true);
            $model = new $this->model;
            foreach($model->findAll($criteria) as $m)
            {
                $this->results[] = $m->{$this->attribute};
            }
 
        }
        echo CJSON::encode($this->results);
    }
}
?>

Simple as that. I have placed this action in my extension folder like:

./webapp/protected/extensions/EAutoCompleteAction.php

Use

And in my controller I declare this action in the public actions function:

Declare action in controller

class MyController extends CController
{
  ...
  public function actions()
  {
    return array(
      'aclist'=>array(
        'class'=>'application.extensions.EAutoCompleteAction',
        'model'=>'My', //My model's class name
        'attribute'=>'my_name', //The attribute of the model i will search
      ),
    );
  }
  ...
}

Use in CJuiAutoComplete widget

So i have a form view like:

  ./webapp/protected/views/my/_form.php

I initialize my widget there like.

<?php 
  $this->widget('zii.widgets.jui.CJuiAutoComplete', array(
      'attribute'=>'my_name',
        'model'=>$model,
        'sourceUrl'=>array('my/aclist'),
        'name'=>'my_input_name',
        'options'=>array(
          'minLength'=>'3',
        ),
        'htmlOptions'=>array(
          'size'=>45,
          'maxlength'=>45,
        ),
  )); ?>

And I am done. Now I can use this CAction in whatever Controller I want for whatever model I want and get quick results.

Total 9 comments

#16490 report it
pjravs at 2014/02/27 09:37pm
Autocomplete showing all results and not filtering

I have this problem. the Autocomplete is not filtering and showing all results. Please help.

http://www.yiiframework.com/forum/index.php/topic/51952-cjuiautocomplete-showing-all-results/

#15794 report it
jwerner at 2013/12/18 03:49am
Nice Extension!

To only get distinct column values, you can add in EAutoCompleteAction/run:

public function run()
{
    if(isset($this->model) && isset($this->attribute)) {
        $criteria = new CDbCriteria();
        // Add:
        $criteria->select = array($this->attribute);
        $criteria->order = $this->attribute;
        $criteria->distinct = true;
        ....

Regards, Joachim

#10439 report it
CodeButterfly at 2012/10/28 07:52pm
About the $results property

Thanks for this wiki. Is there a reason $results is declared as a class property rather than a local variable to the run method?

#8546 report it
Rahmat Awaludin at 2012/06/11 01:24pm
accessRules()

Nice Wiki! Don't forget to add aclist to your accessRules function

public function accessRules()
    {
        return array(
            array('allow',  // allow all users to perform 'index' and 'view' actions
                'actions'=>array('index','view','aclist'),
                'users'=>array('*'),
            ),
            array('allow', // allow authenticated user to perform 'create' and 'update' actions
                'actions'=>array('create','update','download'),
                'users'=>array('@'),
            ),
            array('allow', // allow admin user to perform 'admin' and 'delete' actions
                'actions'=>array('admin','delete'),
                'users'=>array('admin'),
            ),
            array('deny',  // deny all users
                'users'=>array('*'),
            ),
        );
    }
#8506 report it
daydreamer at 2012/06/08 01:39am
Can this handle Unicode

I think, the default autocomplete, doesnot support unicode characters. if i type in english, its showing up. But for other languages it doesnt show up.

Is there any solution for this?

#4898 report it
rei at 2011/08/26 08:05am
Multiple fields output

If you want to return several fields from the controller, you can use something like:

$models = Subcontractor::model()->findAll($criteria);
foreach($models as $model)
{
   $returnVal[] = array(    
      'label'=>...,
      'value'=>...,
      (your other fields)
      'id'=>$model->id,
      'address'=>$model->address,
      'city'=>$model->city,
   );
}
 
echo CJSON::encode($returnVal);
Yii::app()->end();

And in your view, you can get their values like:

$this->widget('zii.widgets.jui.CJuiAutoComplete', array(
  'model'=>$model,
  'attribute'=>'..',
  'source'=>$this->createUrl('...'),
  'options'=>array(
     'showAnim'=>'fold',
     'select'=>"js: function(event, ui) {
         $('#address').val(ui.item['address']);
         $('#city').val(ui.item['city']);
         .....
     }"
  )              
));
#3641 report it
tydeas_dr at 2011/04/26 02:39am
Purpose of the wiki

This wiki initial purpose was to provides it says in the title "A simple action...". I would like to focus on the word simple. What i wanted to is provide a basic functionality for some ppl to start with, that's why I did not released this as an extension. Thank you for your comment will work on it.

#3634 report it
el chief at 2011/04/25 06:44pm
on further inspection

It is lacking several fundamental features:

  1. it should send back the id, value, and optionally label properties. It only sends back the value property. This prevents you from setting the value to a hidden field

  2. It does a %term% style search, whereas a term% style search is more appropriate

  3. it will probably be better performance using DAO

#3633 report it
el chief at 2011/04/25 06:23pm
nice extension

works well, easy setup.

only thing i'd change would be to allow multiple attributes to search on , and use the 'OR' operator in the compare function.

Leave a comment

Please to leave your comment.

Write new article