History Autocomplete

You are viewing revision #2 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.

« previous (#1)next (#3) »

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.

We will use CJuiAutoComplete, what we need is a efficient way for perform searches.

Add this to your components/extensions:

class SearchAction  extends CAction
{
	public $model;
	public $attribute;
	public $criteria=array('limit'=>5);
	
	public function run()
    {
 
 
        $criteria=new CDbCriteria($this->criteria);
        $criteria->addCondition("{$this->attribute} IS NOT NULL AND {$this->attribute} LIKE :param");

		$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);
 
    }
	
}

Now we can configure a search action in our controller like that:

public function actions()
	{
		return array(
			'searchCompany'=>array(
				'class'=>'SearchAction',
				'model'=>'Request',
				'attribute'=>'company',
			)
		);
	}	

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 $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.