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.
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.
on further inspection
It is lacking several fundamental features:
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
It does a %term% style search, whereas a term% style search is more appropriate
it will probably be better performance using DAO
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.
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']); ..... }" ) ));
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?
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('*'), ), ); }
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?
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
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/
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.