Yii. Автокомплит CJuiAutocomplete

Однажды в проекте понадобилось сделать поля с автокомплитом. Далеко идти не пришлось, в Yii есть встроенные возможности в виде CAutocomplete. Однако читаем "Note: CAutoComplete is deprecated since Yii 1.1.3. Consider using CJuiAutoComplete.". Поэтому выбор очевиден.

Итак, имеем два поля с автокомлитом: город и адрес. При этом поиск адреса производится только в данном городе, т.е. нам необходимо передать в автокомлит дополнительный параметр.
Для первого автокомлита "Город" используем простой вызов CJuiAutocomplete.

Представление:


<?= CHtml::activeHiddenField($city, 'id');?>
<?
$this->widget('zii.widgets.jui.CJuiAutoComplete', array(
    'model'=>$city,   // модель
    'attribute'=>'title',  // атрибут модели
    // "источник" данных для выборки
    'source' =>Yii::app()->createUrl('city/autocomplete'),
    // параметры, подробнее можно посмотреть на сайте
    // http://jqueryui.com/demos/autocomplete/
    'options'=>array(
        'minLength'=>'2',
        'showAnim'=>'fold',
        'select' =>'js: function(event, ui) {
            this.value = ui.item.value;
            // записываем полученный id в скрытое поле
            $("#City_id").val(ui.item.id);
            return false;
        }',
    ),
    'htmlOptions' => array(
        'maxlength'=>50,
    ),
));
?>

Контроллер City:

public function actionAutocomplete() {
 $term = Yii::app()->getRequest()->getParam('term');

 if(Yii::app()->request->isAjaxRequest && $term) {
  $cities = City::model()->findAll(array('condition'=>"title LIKE '%$term%'"));
  $result = array();
  foreach($cities as $city) {
   $label = $city['title'];
   $result[] = array('id'=>$city['id'], 'label'=>$label, 'value'=>$label);
  }
  echo CJSON::encode($result);
  Yii::app()->end();
 }
}
"Адрес" будет иметь следующий код.

Представление:

<?
$this->widget('zii.widgets.jui.CJuiAutoComplete', array(
    'model'=> $obj,
    'attribute'=>'id',
    'source' =>'js:function(request, response) {
        $.getJSON("'.$this->createUrl('obj/autocomplete').'", {
  term: request.term.split(/,s*/).pop(),
            city_id: $("#City_id").val()
        }, response);
    }',
    'options'=>array(
        'minLength'=>'2',
        'showAnim'=>'fold',
        'select' =>'js: function(event, ui) {
            this.value = ui.item.id;
            $("#Obj_id").val(ui.item.value);
            return false;
        }',
    ),
    'htmlOptions' => array(
        'maxlength'=>50,
    ),
));
?>
Особое внимание следует обратить на параметр source. В качестве источника данных для выборки здесь используется функция js, а именно JSON запрос, в качестве дополнительного параметра которого выставлен id города из скрытого поля. А уже в контроллере мы принимаем этот параметр и добавляем в условие поиска.

Контроллер Obj:

public function actionAutocomplete() {
    $term = Yii::app()->getRequest()->getParam('term');
    $city_id = Yii::app()->getRequest()->getParam('city_id');

    if(Yii::app()->request->isAjaxRequest && $term && $city_id) {
        $objects = Obj::model()->findAll(array('condition'=>"address LIKE '%$term%' AND city_id = $city_id"));
        $result = array();
        foreach($objects as $obj) {
            $label = $obj['title'] . ', ' . $obj['address'];
            $result[] = array('id'=>$obj['id'], 'label'=>$label, 'value'=>$label);
  }
        echo CJSON::encode($result);
        Yii::app()->end();
    }

}
Вот и все хитрости :)

Комментарии

  1. Не моглм бы расписать в каких контроллерах и представлениях что находится? Не очень понятно 2 раза actionAutocomplete, какой в каком контроллере.

    ОтветитьУдалить
    Ответы
    1. поправила для ясности )
      Представление одно, но каждый автокомплит уходит на свой экшн:
      первый идет на город - сity/autocomplete (смотрим параметр source)
      второй идет на объект - obj/autocomplete (все в том же параметре source)

      Удалить
  2. Спасибо, отличный пример, всё работает. Спасибо Вам!

    ОтветитьУдалить
  3. Ты крута, подруга! Спасибо за отличный пост и отличный блог!
    Умна ещё и красотка, рад за тебя :)

    ОтветитьУдалить
  4. Спасибо! В закладки!)

    ОтветитьУдалить
  5. что значит findAll(array('condition'=>"title LIKE '%$term%'"));

    ОтветитьУдалить
  6. Максиму: это значит что "надо выбрать все названия, где присутствует строка $term - не важно, в начале она, в середине или в конце".

    ОтветитьУдалить
  7. что такое getParam('term') откуда они приходят?

    ОтветитьУдалить
    Ответы
    1. В методе getJSON вторым параметром мы передаем нужные нам данные, в том числе term

      Удалить
    2. В упор не вижу, где у Вас метод getJSON?

      Удалить
    3. Ctrl+F попробуйте, помогает ;)

      Удалить
    4. Этот комментарий был удален автором.

      Удалить
  8. Вы не могли бы подправить этот скрипт под YII2. в YII2 -он не работает...

    ОтветитьУдалить
    Ответы
    1. С Yii2 не работала и в ближайшее время не планирую. Сорри )

      Удалить

Отправить комментарий

Популярные сообщения