Difference between #2 and #1 of History Autocomplete

unchanged
Title
History Autocomplete
unchanged
Category
How-tos
unchanged
Tags
autocomplete
changed
Content
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 function activeTextFieldHistory($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 can pass additional configuration for the
search (e.g, some more condition limiting theconfigure a
search action in a project/group, sorting or whatever else)

And add this to your SiteController:our controller like that:



~~~
[php]

	public	public function
actionSearch()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.