History Autocomplete

You are viewing revision #1 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.

next (#2) »

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:

class ZHtml extends CHtml
{
	public function activeTextFieldHistory($model, $attribute, $htmlOptions=null)
	{

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

You can pass additional configuration for the search (e.g, some more condition limiting the search in a project/group, sorting or whatever else)

And add this to your SiteController:

public function actionSearch()
	{
	
		$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);
	
	} 

Now you can create your search textfield as:

ZHtml::activeTextFieldHistory($model, 'color');

This method is quite efficient and usually customer like it, because is based on the laziness of the users.