Posts Tagged autocomplete

How to customize appearance of CJuiAutoComplete in Yii

Before we go to the point of this post let’s start with some basics. It is quite easy to use CJuiAutoComplete widget in your form. Basically you have to add the widget to your form:


$form->widget('zii.widgets.jui.CJuiAutoComplete', array(
  'name' => 'field_name',
  'value' => $model->field_name,
  'sourceUrl' => array('some_view/autoComplete'),
  'options'=>array(
  'minLength' => '2',
  'showAnim' => 'fold',
  'select' => "js: function(event, data) {
    alert(data.item['id']);
  }"
)));

This widget will use ‘sourceUrl’ (ie. autoComplete action of some_view) as a source of possible option to choose from. The function defined in ‘select’ parameter will be triggered when user chooses a value from the list. Other options are rather self descriptive and less important. More info you can find in yii and jquery documentation.

Now, the widget expects that data returned by the action is in JSON format. Here is an example of such action:

public function actionAutoComplete($term) {
  $retVal = array();

  if (strlen($term) >= 2) {
    $model = Wbs::model();

    $criteria = new CDbCriteria();
    $criteria->compare('some_field', $term, true);
    $criteria->compare('other_field', $term, true, 'OR');
    $criteria->compare('another_field', $term, true, 'OR');

    $criteria->limit = 10;

    foreach($model->findAll($criteria) as $item) {
      $retVal[] = array(
        'label' => $item->some_field,
        'value' => $item->some_field,
        'id' => $item->id,
        'other_field' => $item->other_field,
        'another_field' => $item->another_field,
     );
   }
 }

 echo CJSON::encode($retVal);
 Yii::app()->end();
}

Now we’re going to the point. It’s plain to see that it is not a problem to add some other fields to the query, but how to show some more values on the list of autocomplete? In this case jquery documentation can be very helpful (while yii’s docs says nothing about it). What you need to do is add method (or rather replace default one) which renders each element on a list of possible values:

jQuery('#field_name').data('autocomplete')._renderItem = function( ul, item ) {
  return $('<li></li>')
    .data('item.autocomplete', item)
    .append('<a>' + item.some_value + '<br><i>' + item.other_value + '</i></a>')
    .appendTo(ul);
};

I think that it’s easy to see in the above code that the “item” is one element of JSON array returned from autoComplete action and in the function you can use its values.

And there are some important things. First and foremost, ‘#field_name’ has to match the name which is used when CJuiAutoComplete widget is created. Secondly, this javascript code has to be executed when you are sure that this autocomplete element is already initialized in the document! To do this you can use yii’s registerScript() method with CClientScript::POS_READY parameter.

Yii::app()->clientScript->registerScript('autocomplete', "
  jQuery('#field_name').data('autocomplete')._renderItem = function( ul, item ) {
    return $('<li></li>')
      .data('item.autocomplete', item)
      .append('<a>' + item.some_value + '<br><i>' + item.another_value + '</i></a>')
      .appendTo(ul);
  };",
  CClientScript::POS_READY
);
Advertisements

, ,

5 Comments