繁体   English   中英

yii2:下拉选择字段,如

[英]yii2: dropdown select field with like

我有一个下拉选择字段,其中包含很长的值列表,我想像搜索一样从列表中选择值,以便更轻松地选择列表中的值,例如:

我有

DR X
DR Y
Dr Z

因此,如果输入Z,则突出显示值Dr Z以供选择。 现在,我必须键入Z博士以突出显示该值。

我的下拉列表代码如下:

<?= $form->field($model, 'doctor_name')->DropDownList(ArrayHelper::map(\app\models\Doctor::find()->all(), 'id', 'doctor_name' ),
[ 'prompt' => 'Please Select' ]) ?>

寻找一些提示。

您正在寻找的是类似于jQuery Ui组合框的东西。 如何在软件中实施此操作有多种方法,但这是一种方法:

制作一个组合框小部件

Yii2带有多个jquery-ui小部件。 第一步是为Yii2安装JUI

完成此操作后,您将可以访问所有这些小部件。 但是,没有组合框小部件(只有一个标准的自动完成小部件)。 没关系,我们仍然可以使用此插件中的资产。

为小部件制作一个AssetBundle

创建一个ComboboxAssetBundle.php文件,将其放入assets文件夹中。 它应如下所示(这是advanced templatefrontend入口点的示例):

namespace frontend\assets;

use yii\web\AssetBundle;

class ComboboxAssetBundle extends AssetBundle
{
    public $sourcePath = '@frontend/assets';
    public $css = [
    ];
    public $js = [
        'js/combobox.js', // Lets load your custom JS
    ];
    public $depends = [
        'yii\web\JqueryAsset', // requires Jquery
        'yii\jui\JuiAsset', // requires JUI
    ];
}

您的@frontend/assets/js/combobox.js文件应包含combobox js代码:

(function( $ ) {
    $.widget( "custom.combobox", {
      _create: function() {
        this.wrapper = $( "<span>" )
          .addClass( "custom-combobox" )
          .insertAfter( this.element );

        this.element.hide();
        this._createAutocomplete();
        this._createShowAllButton();
      },

      _createAutocomplete: function() {
        var selected = this.element.children( ":selected" ),
          value = selected.val() ? selected.text() : "";

        this.input = $( "<input>" )
          .appendTo( this.wrapper )
          .val( value )
          .attr( "title", "" )
          .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
          .autocomplete({
            delay: 0,
            minLength: 0,
            source: $.proxy( this, "_source" )
          })
          .tooltip({
            tooltipClass: "ui-state-highlight"
          });

        this._on( this.input, {
          autocompleteselect: function( event, ui ) {
            ui.item.option.selected = true;
            this._trigger( "select", event, {
              item: ui.item.option
            });
          },

          autocompletechange: "_removeIfInvalid"
        });
      },

      _createShowAllButton: function() {
        var input = this.input,
          wasOpen = false;

        $( "<a>" )
          .attr( "tabIndex", -1 )
          .attr( "title", "Show All Items" )
          .tooltip()
          .appendTo( this.wrapper )
          .button({
            icons: {
              primary: "ui-icon-triangle-1-s"
            },
            text: false
          })
          .removeClass( "ui-corner-all" )
          .addClass( "custom-combobox-toggle ui-corner-right" )
          .mousedown(function() {
            wasOpen = input.autocomplete( "widget" ).is( ":visible" );
          })
          .click(function() {
            input.focus();

            // Close if already visible
            if ( wasOpen ) {
              return;
            }

            // Pass empty string as value to search for, displaying all results
            input.autocomplete( "search", "" );
          });
      },

      _source: function( request, response ) {
        var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
        response( this.element.children( "option" ).map(function() {
          var text = $( this ).text();
          if ( this.value && ( !request.term || matcher.test(text) ) )
            return {
              label: text,
              value: text,
              option: this
            };
        }) );
      },

      _removeIfInvalid: function( event, ui ) {

        // Selected an item, nothing to do
        if ( ui.item ) {
          return;
        }

        // Search for a match (case-insensitive)
        var value = this.input.val(),
          valueLowerCase = value.toLowerCase(),
          valid = false;
        this.element.children( "option" ).each(function() {
          if ( $( this ).text().toLowerCase() === valueLowerCase ) {
            this.selected = valid = true;
            return false;
          }
        });

        // Found a match, nothing to do
        if ( valid ) {
          return;
        }

        // Remove invalid value
        this.input
          .val( "" )
          .attr( "title", value + " didn't match any item" )
          .tooltip( "open" );
        this.element.val( "" );
        this._delay(function() {
          this.input.tooltip( "close" ).attr( "title", "" );
        }, 2500 );
        this.input.autocomplete( "instance" ).term = "";
      },

      _destroy: function() {
        this.wrapper.remove();
        this.element.show();
      }
    });
  })( jQuery );

制作小部件

完成以上所有操作后,您需要创建小部件。 为了与上述保持一致,请使用以下内容制作一个@frontend/widgets/Combobox.php文件:

namespace frontend\widgets;

use yii\base\Widget;
use frontend\assets\ComboboxAssetBundle;
use yii\base\InvalidConfigException;
use yii\helpers\Html;
use yii\helpers\ArrayHelper;
use Yii;

class Combobox extends Widget
{
    /**
     * @var form object if desired
     */
    public $form;

    /**
     * @var model object tu use
     */
    public $model;

    /**
     * @var model attribute this dropdown is for.
     */
    public $attribute;

    /**
     * @var options for the dropdown.
     */
    public $options = [];

    /**
     * @var items for the dropdown list.
     */
    public $items = [];

    public function init()
    {
        if(!isset($this->attribute))
        {
            throw new InvalidConfigException("an attribute is required");
        }
    }

    public function run()
    {
        //register your asset:
        ComboboxAssetBundle::register(Yii::$app->view);
        Yii::$app->view->registerJs('$( ".combobox" ).combobox();');

        //add a class to the options
        $options = ArrayHelper::merge($this->options, ['class'=>'combobox']);

        if(isset($this->form))
        {
            return $this->form->field($this->model, $this->attribute)->dropDownList($this->items, $options);
        }
        elseif(isset($this->model))
        {
            return Html::activeDropDownList($this->model, $this->attribute, $this->items, $options);
        }
        else
        {
            return Html::dropDownList($this->attribute, NULL, $this->items, $options);
        }
    }
}

调用小部件

这样,您应该可以使用Combobox::widget([])调用小部件,如下所示:

<?= Combobox::widget([
    'form' => $form,
    'model' => $model,
    'attribute' => 'doctor_name',
    'items' => ArrayHelper::map(\app\models\Doctor::find()->all(), 'id', 'doctor_name' ),
    'options' => [ 'prompt' => 'Please Select' ]) ?>

我尚未对此进行测试,但是应该有足够的信息供您轻松使用。 这样做的好处是您将能够在应用程序中的任何地方重用这种类型的下拉列表。

让我知道您是否需要任何其他信息。

编辑:

有时,您需要让您的应用程序强制复制您的资产,否则您将看不到任何更改。 有许多方法可以执行/配置,但是在您的开发环境中是本地的,我发现最简单的方法是在local配置文件中添加以下内容:

'components' => [
    //...
    'assetManager' => [
        'forceCopy' => TRUE,
    ]
],

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM