unchanged
Title
History Autocomplete
What for? ------------------ In application development we often have to choose how to mange recurrent values. For example, a field color for a cloath. You cannot leave free text, because there whould be too much typos, but you cannot enumerate all possibility because they are a lot and sometime there are new colors. Often you can solve with a foreign field, with an interface for add a new color. That's great if adding new color is a quite rare operation, if it happens too often and if the users are too stupid for remember how to add a color, it can be odd. I propose an half way solution: a free text with autocomplete based on history values.Add this to an CHtml extension:We will use CJuiAutoComplete, what we need is a efficient way for perform searches. Add this to your components/extensions: ~~~ [php]class ZHtml extends CHtmlclass SearchAction extends CAction { public $model; public $attribute; public $criteria=array('limit'=>5); public functionactiveTextFieldHistory($model, $attribute, $htmlOptions=null) {run() { $criteria=new CDbCriteria($this->criteria); $criteria->addCondition("{$this->attribute} IS NOT NULL AND {$this->attribute} LIKE :param");$mod=$model; $attr=$attribute; self::resolveNameID($mod,$attr,$htmlOptions); $route=array('/site/search', 'model'=>get_class($model), 'attribute'=>$attr); if (isset($htmlOptions['filter'])) { $route['filter']=$htmlOptions['filter']; unset($htmlOptions['filter']); } $this->widget('zii.widgets.jui.CJuiAutoComplete', array('model'=>$model, 'attribute'=>$attr, 'htmlOptions'=>$htmlOptions, 'sourceUrl'=>$route)); }$criteria->group=$this->attribute; $criteria->order="COUNT({$this->attribute}) desc"; $criteria->params[':param']='%'.$_GET['term'].'%'; $results=array(); foreach (CActiveRecord::model($this->model)->findAll($criteria) as $record) $results[]=$record->{$this->attribute}; echo CJSON::encode($results); } } ~~~YouNow we canpass additional configuration for the search (e.g, some more condition limiting theconfigure a search action ina project/group, sorting or whatever else) And add this to your SiteController:our controller like that: ~~~ [php]publicpublic functionactionSearch()actions() {$model=$_GET['model']; $attribute= $_GET['attribute']; $param=addslashes($_GET['term']); $results=array(); $criteria=new CDbCriteria; $criteria->condition="$attribute IS NOT NULL AND $attribute LIKE '%$param%' "; if (isset($_GET['filter'])) $criteria->condition.=' AND '.$_GET['filter']; $criteria->group=$attribute; $criteria->order="COUNT($attribute) desc"; $criteria->limit=5; $records=CActiveRecord::model($model)->findAll($criteria); foreach ($records as $record) $results[]=$record->$attribute; echo CJSON::encode($results); }return array( 'searchCompany'=>array( 'class'=>'SearchAction', 'model'=>'Request', 'attribute'=>'company', ) ); } ~~~Now you can create your search textfield as:You can pass additional configuration for the search (e.g, some more condition limiting the search in a project/group, sorting or whatever else) using the property $criteria. Now you can create your search textfield as: ~~~ [php]ZHtml::activeTextFieldHistory($model, 'color');<?php $this->widget('zii.widgets.jui.CJuiAutoComplete', array('model'=>$model, 'attribute'=>'company', 'htmlOptions'=> array('maxlength'=>300, 'class'=>'text'), 'sourceUrl'=>'searchCompany'));?> ~~~ This method is quite efficient and usually customer like it, because is based on the laziness of the users.