Display custom layout in autocomplete in Yii

2019-04-17 15:26发布

问题:

My problem is, I want to customize the drop-down list of autocomplete.Below is my tried code but it is not displaying as I want.

<?php
$this->widget('zii.widgets.jui.CJuiAutoComplete', array(
    'name'=>'autoComplete',
     'value'=>'',
     'source'=>$this->createUrl('post/search'),
     // additional javascript options for the autocomplete plugin
     'options'=>array(
          'showAnim'=>'fold',
     ),'htmlOptions'=>array(
     //'onfocus' => 'js: this.value = null; $("#searchbox").val(null); $("#selectedvalue").val(null);',
     'class' => 'input-xxlarge search-query',
     'placeholder' => "Search...",
     'methodChain'=>'.data( "ui-autocomplete" )._renderItem = function( ul, item ) {
          return $( "<li>" )
              .data( "item.autocomplete", item )
              .append( "<a>" + item.name +  "</a>" )
              .appendTo( ul );
      };'
   ),
));
?>

It should create <li> and append <a></a> to it without any class. But it is not working and displaying the default drop-down list.

Thanks

回答1:

This is the image of the result which i was getting previously.

And my desired result is

So first of all I changed the function which was giving me only one column's data. This is the code from my controller.

public function actionSearch()
{
    $res =array();

    if (isset($_GET['term'])) {
        // sql query to get execute
        $qtxt ="SELECT id,name,description,image FROM table_name WHERE name LIKE :name";
        // preparing the sql query
        $command =Yii::app()->db->createCommand($qtxt);
        // assigning the get value
        $command->bindValue(":name", '%'.$_GET['term'].'%', PDO::PARAM_STR);
        //$res =$command->queryColumn(); // this is the function which was giving me result of only 1 column
        $res =$command->queryAll(); // I changed that to this to give me result of all column's specified in sql query.
    }
    echo CJSON::encode($res); // encoding the result to JSON
    Yii::app()->end();
}

To accomplish to process the multiple column data result we require our own widget which will give us option to process that result. This code I have taken from here.

Where to save this file?

  • Go inside project_directory\protected\extensions folder. Note This path is for windows system.
  • Create a php file named as myAutoComplete.php
  • Now paste this code inside this file

Code

<?php
// below line is necessary otherwise this class will not be able to extend the CJuiAutoComplete class
Yii::import('zii.widgets.jui.CJuiAutoComplete');  
class myAutoComplete extends CJuiAutoComplete
{
/**
 * @var string the chain of method calls that would be appended at the end of the autocomplete constructor.
 * For example, ".result(function(...){})" would cause the specified js function to execute
 * when the user selects an option.
 */
public $methodChain;
/**
 * Run this widget.
 * This method registers necessary javascript and renders the needed HTML code.
 */
public function run()
{
    list($name,$id)=$this->resolveNameID();

    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::activeTextField($this->model,$this->attribute,$this->htmlOptions);
    else
        echo CHtml::textField($name,$this->value,$this->htmlOptions);

    if($this->sourceUrl!==null)
        $this->options['source']=CHtml::normalizeUrl($this->sourceUrl);
    else
        $this->options['source']=$this->source;

    $options=CJavaScript::encode($this->options);

    $js = "jQuery('#{$id}').autocomplete($options){$this->methodChain};";

    $cs = Yii::app()->getClientScript();
    $cs->registerScript(__CLASS__.'#'.$id, $js);
    }
}

Now you have created an extension here and now you can use it in your view.

Code for View

<div id="search">
        <?php
        $this->widget('ext.myAutoComplete', array(
            'id'  => 'searchbox',
            'name'=> 'autoComplete',
            'source'=>'js: function(request, response) {
            $.ajax({
                url: "'.$this->createUrl('post/search').'",
                dataType: "json",
                data: {
                    term: request.term,
                    brand: $("#type").val()
                },
                success: function (data) {
                    response(data);
                }
            })
            }',
            'options' => array(
                'showAnim' => 'fold',
            ),
            'htmlOptions' => array(
                'placeholder' => "Search...",
            ),
            'methodChain'=>'.data( "autocomplete" )._renderItem = function( ul, item ) {
                return $( "<div class=\'drop_class\'></div>" )
                    .data( "item.autocomplete", item )
                    .append( "<a href=\'" + item.id + "\'><div style=\'width:22%; float:left;\'><img height=50 width=50 src=\'' . Yii::app()->request->baseUrl.'/banner/' . '" + item.image + "\'></div><div style=\'width:78%;float:left;\'>" +item.description +  "</div></a>" )
                    .append("<div style=\'clear:both;\'></div>")
                    .appendTo( ul );
            };'
        ));
        ?>
    </div>

Now you have noticed that I have used methodChain option in autocomplete widget to add extra content in drop-down. This feature we get because we have used our new customised autocomplete widget.



回答2:

The classes are set by the jQuery autocomplete so this isn't specific to Yii. Unfortunately you cannot override them like that.

You can either create your own custom CSS for the classes it uses as explained here: Jquery autocomplete styling

Or work with the 'open' method to modify the style when the dropdown is opened. That's also explained under the link above but further down.

Update: Based on the linked answer and using your example you could change the background-color for the <li> elements using this:

    $this->widget('zii.widgets.jui.CJuiAutoComplete', array(
        'name'=>'autoComplete',
        'value'=>'',
        'source'=>$this->createUrl('post/search'),
        // additional javascript options for the autocomplete plugin
        'options'=>array(
                'showAnim'=>'fold',
                'open'=> 'js:function(e, ui) {$(".ui-menu-item").css("background-color","#FF0000");}'
        ),
));

That means you can change the styles on the fly but you can't get rid of the classes completely as they are hard-coded into the jQuery method.

You could also use ThemeRoller to create your own custom theme for the autocomplete.