Yii: Автокомплит CJuiAutoComplete для выбора значения поля из другой модели и добавления этого значения в поле

Yii: Автокомплит CJuiAutoComplete для выбора значения поля из другой модели и добавления этого значения в поле Делаем выпадающий список на javascript для выбора значения из другой модели (таблицы, Movie) в поле текущей модели (Article).

Для автокомплита (выпадающий список со значениями, которые соответствуют набираемому в поле тексту) в Yii используется виджет CJuiAutoComplete (до версии Yii 1.1.3 был CAutoComplete).

Он построен на JQuery (см. описание Autocomlete widget).

Yii CJuiAutoComplete, автокомплит в Yii

1. В представлении /views/article/_form.php

<div class="row">
 <?php echo $form->labelEx($model,'movie_id'); ?>
 <?php echo CHtml::script("
     function split(val) {
      return val.split(/,\s*/);
     }
     function extractLast(term) {
      return split(term).pop();
     }
   ")?>
 <?php $this->widget('zii.widgets.jui.CJuiAutoComplete', array(
   'model'=>$model,
   'attribute'=>'movie',
//'value' => $model->id,
   'source'=>"js:function(request, response) {
      $.getJSON('".$this->createUrl('suggest')."', {
        term: extractLast(request.term)
      }, response);
      }",
   'options'=>array(
     'delay'=>300,
     'minLength'=>2,
     'showAnim'=>'fold',
 'multiple'=>true,
     'select'=>"js:function(event, ui) {
         var terms = split(this.value);
         // remove the current input
         terms.pop();
         // add the selected item
         terms.push( ui.item.value );
         // add placeholder to get the comma-and-space at the end
         terms.push('');
         this.value = terms.join(', ');
         return false;
       }",
   ),
   'htmlOptions'=>array(
     'size'=>'40'
   ),
  ));
  // Для подсветки набираемого куска запроса в предлагаемом списке
  Yii::app()->clientScript->registerScript('unique.script.identifier', "
 $('#Article_movie').data('autocomplete')._renderItem = function( ul, item ) {
   var re = new RegExp( '(' + $.ui.autocomplete.escapeRegex(this.term) + ')', 'gi' );
   var highlightedResult = item.label.replace( re, '<b>$1</b>' );
   return $( '<li></li>' )
     .data( 'item.autocomplete', item )
     .append( '<a>' + highlightedResult + '</a>' )
     .appendTo( ul );
 };
");  
?>
</div>

2. В контроллере /controllers/ArticleController.php

public function actionSuggest(){
 if (Yii::app()->request->isAjaxRequest && isset($_GET['term'])) {
  $models = Movie::model()->suggestTag($_GET['term']);
  $result = array();
  foreach ($models as $m)
   $result[] = array(
     'label' => $m->title." (".$m->year.")",
     'value' => $m->title,
     'id' => $m->id,
   );

  echo CJSON::encode($result);
 }
} 

В модели Movie.php должны присутствовать поля – id, title, year.

3. Функция suggestTag, которую вызвали из модели Movie (находится в models/Movie.php)

public function suggestTag($keyword){
 $tags=$this->findAll(array(
   'condition'=>'title LIKE :keyword OR year LIKE :keyword',
   'params'=>array(
     ':keyword'=>'%'.strtr($keyword,array('%'=>'\%', '_'=>'\_', '\\'=>'\\\\')).'%',
   )
 ));
 return $tags;
}

Замечание: при таком автокомплите в таблице, которая соответствует модели Article мы имеем поле 'movie', которое дублирует поле 'title' из таблицы Movie. Что не есть хорошо.

В курсе по Yii покажу как сделать автокомплит на CJuiAutoComplete более оптимизированным для базы данных, то есть сохранять в таблицу не значение, а id, который соответствует значению в другой таблице. Но отображать в поле CJuiAutoComplete именно значение (ведь id, как таковой, нам ни о чём не говорит, это только цифра).

P.S. В развитие темы - написали о том, как сделать Множественный автокомплит с помощью CJuiAutoComplete (автокомплит нескольких значений в одно поле).

Источник: loco.ru

almix
Разработчик Loco, автор статей по веб-разработке на Yii, CodeIgniter, MODx и прочих инструментах. Создатель Team Sense.

Вы можете почитать все статьи от almix'а.



Другие статьи по этой теме:

Комментарии (4)     Подпишитесь на RSS комментариев к этой статье.

4 комментариев

#879
Alex говорит:
May 22, 2013 at 11:45 pm
Впоследнемабзацеобещалисложныйпример, авпрограммекурсаегонет. Поделитесь, плз. Илидайтеподсказку, плз
#891
almix говорит:
May 31, 2013 at 12:55 am
Да, будет в Курсе.
#1363
Сергей говорит:
April 23, 2015 at 10:03 am
Еще не забыть добавить в accessRules правило для suggest в файле ArticleController.php
#1364
almix говорит:
April 27, 2015 at 09:51 am
Спасибо, всё учту. Добавил в программу курса.