I’ve spent quite some time looking at how autocompletion is meant to work with yii. Is there any consensus at all? As far as I can see there are three wiki entries and this seems to be the most popular.
However, there is a comment by the author pointing out a different much simpler way. Is that what is supposed to be done? If so, can I edit the entry to point that out? Rather than go through the whole dance to realise it’s not the best way?
There is also this frequently referenced thread where people kind of come to conclusions but there is no fully working example either.
Rather than just bitch, I’ll try to summarise my findings to see if what I’m doing makes sense and hopefully help other noobs see the light. The goal is to get autocompletion to work and also populate {(multiple) hidden} fields as a bonus. A lot of the “incomprehensible” stuff is explained at the JQuery UI site:
-
In the view you need a field to write in. This triggers the autocompletion, asking the controller for results.
-
The controller needs a function that can provide answers to the view when it’s asking.
Example code for the view
<?php echo $form->hiddenField($model, 'id'); // one way of creating a hidden field?>
<?php
// ext is a shortcut for application.extensions
$this->widget('zii.widgets.jui.CJuiAutoComplete', array(
'id'=>'fname',// set the "id" html attributes for the text field
'name'=>'fname',// set the name attribute
'source'=>$this->createUrl('autocomplete'), // calls the actionAutocomplete function
//in the controller
'options'=>array(
'delay'=>300, // wait 300ms after user stops typing
'minLength'=>2, // length of entered characters before completing
// CRUCIAL: when the user selects one of the predicted options,
// this populates the hidden field with the "id" part of the returned json data
'select'=>"js:function(event, ui) {
$('#SessionLog_id').val(ui.item.id); // ui.item.whatYouReturnInController
// #SessionLog_id is the id of the hidden field
}"
),
'htmlOptions'=>array(
'size'=>'40' // set size of the input box, optional
),
));
?>
The controller code is very unpolished but I’ll try to explain:
public function actionAutocomplete(){
$res = array();
// read the search "term" we've been asked about
$term = Yii::app()->getRequest()->getParam('term', false);
if ($term)
{
// tablename is user
// fname is being formatted as "value" because that's what jQuery needs!
// name seems to be what gets replaced by our search term
$sql = 'SELECT id, fname AS "value" FROM `user` where LCASE(fname) LIKE :name';
$cmd = Yii::app()->db->createCommand($sql);
// use "name" as search term?
$cmd->bindValue(":name","%".strtolower($term)."%", PDO::PARAM_STR);
// get all results
$res = $cmd->queryAll();
}
echo CJSON::encode($res);
Yii::app()->end();
}
The last thing that had me stuck was returning the data as “value” because that’s what ends up in the box that the autocompletion runs in.
Does this all make sense? Am I right in considering the Wiki entries obsolete with overriding classes etc?