Usually when we use AutoComplete in a project, We need to show "title" or "name" in the list, while when the form is posted, we need some sort of integer ID referring to the selected value. Out of the Box, CJuiAutoComplete widget doesn't provides different display text and post values.
Here's the simplest way to do it:
Create a new file /protected/extensions/MyAutoComplete.php and put the following content in it:
Yii::import("zii.widgets.jui.CJuiAutoComplete"); class myAutoComplete extends CJuiAutoComplete { /** * Run this widget. * This method registers necessary javascript and renders the needed HTML code. */ public function run() { list($name,$id)=$this->resolveNameID(); // Get ID Attribute of actual hidden field containing selected value $attr_id = get_class($this->model).'_'.$this->attribute; if(isset($this->htmlOptions['id'])) $id=$this->htmlOptions['id']; else $this->htmlOptions['id']=$id; if(isset($this->htmlOptions['name'])) $name=$this->htmlOptions['name']; if($this->hasModel()) { echo CHtml::textField($name,$this->value,$this->htmlOptions); echo CHtml::activeHiddenField($this->model, $this->attribute); }else { echo //CHtml::textField($name,$this->value,$this->htmlOptions); //CHtml::hiddenField($name,$this->value,$this->htmlOptions); } if($this->sourceUrl!==null) $this->options['source']=CHtml::normalizeUrl($this->sourceUrl); else $this->options['source']=$this->source; // Modify Focus Event to show label in text field instead of value if (!isset($this->options['focus'])) { $this->options['focus'] = 'js:function(event, ui) { $("#'.$id.'").val(ui.item.label); return false; }'; } if (!isset($this->options['select'])) { $this->options['select'] = 'js:function(event, ui) { $("#'.$id.'").val(ui.item.label); $("#'.$attr_id.'").val(ui.item.id); }'; } $options=CJavaScript::encode($this->options); //$options = $this->options; $js = "jQuery('#{$id}').autocomplete($options);"; $cs = Yii::app()->getClientScript(); $cs->registerScript(__CLASS__.'#'.$id, $js); } }
// Important: The Method below must return each record with id, label keys. See how i've wrote the query "title AS label" below. /* Result should be in this format array( 'id'=>4, 'label'=>'John', ), array( 'id'=>3, 'label'=>'Grace', ), array( 'id'=>5, 'label'=>'Matt', ), */ public static function usersAutoComplete($name='') { // Recommended: Secure Way to Write SQL in Yii $sql= 'SELECT id ,title AS label FROM users WHERE title LIKE :name'; $name = $name.'%'; return Yii::app()->db->createCommand($sql)->queryAll(true,array(':name'=>$name)); // Not Recommended: Simple Way for those who can't understand the above way. // Uncomment the below and comment out above 3 lines /* $sql= "SELECT id ,title AS label FROM users WHERE title LIKE '$name%'"; return Yii::app()->db->createCommand($sql)->queryAll(); */ }
Create an action in your controller to return list of suggestions in JSON Format, as follows:
public function actionUsersAutocomplete() { $term = trim($_GET['term']) ; if($term !='') { // Note: Users::usersAutoComplete is the function you created in Step 2 $users = Users::usersAutoComplete($term); echo CJSON::encode($users); Yii::app()->end(); } }
Finally, Open the view file and add the following widget where you need the AutoComplete Text Field. _Notes:_ 1. attribute=>'user_id' property, set this to your actual field name in Database. 2. name=>'user_autocomplete', try to make a habit of naming the autocomplete field ending with _autocomplete or use your own convention.
// Note: ext.MyAutoComplete is equivalent/shortcut to application.extensions.MyAutoComplete // This means Look for protected/extensions/MyAutoComplete.php file $this->widget('ext.myAutoComplete', array( 'model'=>$model, 'attribute'=>'user_id', 'name'=>'user_autocomplete', 'source'=>$this->createUrl('orders/usersAutoComplete'), // Controller/Action path for action we created in step 4. // additional javascript options for the autocomplete plugin 'options'=>array( 'minLength'=>'0', ), 'htmlOptions'=>array( 'style'=>'height:20px;', ), ));
Done!
Now when you post the form, you get the ID of selected value. Let me know if someone is still unable to follow this and i'll be glad to help. Also please comment if you think there's a better and simpler way to do this.
Total 1 comment
Nothing major but problem with your comment...
Leave a comment
Please login to leave your comment.