如何根据选项类动态过滤 select2 列表

Posted

技术标签:

【中文标题】如何根据选项类动态过滤 select2 列表【英文标题】:How to dynamically filter a select2 listing based on option class 【发布时间】:2017-04-12 05:10:47 【问题描述】:

我有一个可选的“机会”(在下面的示例中为id="opportunities")的下拉选择,我使用select2 jquery plugin 对其进行了增强,并希望动态过滤此列表以减少使用时提供给用户的可能选项第二个选择下拉菜单(在下面的示例中为id="group-select"),

<label>
  Select an opportunity<br>
  <select id="opportunities" style="width:300px;" multiple="multiple" name="selected-opps" value="">
    <optgroup label="Class A">
      <option class="group-1" value="1a">Opportunity 1a</option>
      <option class="group-2" value="2a">Opportunity 2a</option>
    </optgroup>
    <optgroup label="Class B">
      <option class="group-1" value="1b">Opportunity 1b</option>
      <option class="group-2" value="2b">Opportunity 2b</option>
    </optgroup>
    <optgroup label="Class C">
      <option class="group-1" value="1c">Opportunity 1c</option>
      <option class="group-2" value="2c">Opportunity 2c</option>
    </optgroup>
  </select>
</label>
<select id="group-select">
  <option value="">Select a group</option>
  <option value="group-1">group 1</option>
  <option value="group-2">group 2</option>
</select>
</div>
<div id="select-opportunity"></div>
<script type="text/javascript">
(function( $ ) 
  'use strict';

   var opportunities = $('select#opportunities').select2(
    dropdownParent: $('#select-opportunity')
  );
)( jQuery );
</script>

我希望能够在第二个选择中进行选择,例如“组 1”,并希望 select2 列表仅包含“组 1”项,根据第一个选择下拉列表中的选项,具有 @ 987654325@类属性。

【问题讨论】:

【参考方案1】:

我设法使用 select2 插件提供的 2 个可选功能解决了这个问题,即使用templating functionality 控制项目构建和显示方式的能力,以及使用插件中公开的programmatic control。我将问题中示例下方附加的 javascript 替换为,

<script type="text/javascript">
(function( $ ) 
  'use strict';

  var opportunities = $('select#opportunities').select2(
    dropdownParent: $('#select-opportunity'),
    templateResult: formatItem
  );
  function formatItem (state) 
    if (!state.id)  return state.text; 
    //change the id of our select2 items
    state._resultId = state._resultId+'-'+state.element.className;
    var $state = $(
      '<span class="opportunity-item ' + state.element.className + '">' + state.text + '</span>'
    );
    return $state;
  
  $('select#group-select').change( function() 
    //hide the unwanted options
    var group = $('select#group-select option:selected').val();
    //clear the styling element
    $('style#select2-style').empty();

    if(group)
      //if a group is selected we need to hide all the others
      $('select#group-select option').not(':selected').each(function()
        group = $(this).val();
        if(group)
          $('style#select2-style').append(
           'li[id$="'+group+'"]display:none;'
          );
        
      );
    
    //force the select2 to referesh by opening and closing it again
    opportunities.select2('open');
    opportunities.select2('close');
  );


)( jQuery );
</script>
<style id="select2-style"></style>

我还在底部添加了一个空的&lt;style&gt; 元素,我在其中动态创建了隐藏不需要的项目所需的规则。

逻辑

上面的代码创建了模板函数formatItem,select2 插件将使用它来格式化项目。项目 state 对象被传递给包含每个项目的唯一 id 的函数。

这个id是通过附加相应选项元素的类来修改的。

当在第二个下拉选择 (#group-select) 中选择组选项时,会创建一组样式并将其附加到底部 &lt;style&gt; 元素以隐藏所有 id 属性以类名结尾的元素被隐藏,例如如果选择了 group-1,代码将创建一个样式来隐藏 group-2 项目,

li[id$="group-2"]  
  display:none;

但是,要使其正常工作,我们需要强制刷新 select2 下拉菜单以获取新样式,而我为这项工作找到的唯一方法是使用插件的编程控制来“打开”并立即“关闭” select2 下拉菜单。

【讨论】:

【参考方案2】:

ّ简短的例子。

window.templateResult = function templateResult(state) 
            if (state.text.indexOf('ss') == -1)
                return null;///hide

            if (!state.id)  return state.text; 
            var $state = $(
              '<span>' + state.text + '</span>'
            );
            return $state;
        ;

        //Init
        $("#select1").select2(
            templateResult: templateResult
        );

ّ下面的完整示例。

$(document).ready(function () 

            //general custom filter
            window.Select2FilterFunc = function (state)  return "Default" ;

            //general custom templateResult
            window.templateResult = function templateResult(state) 

                //call custom filter
                var result = Select2FilterFunc(state);
                if (result != "Default")
                    return result;

                if (!state.id)  return state.text; 
                var $state = $(
                  '<span>' + state.text + '</span>'
                );
                return $state;
            ;

            //Init
            $("#select1").select2(
                templateResult: templateResult
            );

            //Add Custom Filter when  opening
            $('#select1').on('select2:opening', function (evt) 

                //set your filter
                window.Select2FilterFunc = function (state) 
                    if (state.text.indexOf('ss') == -1)
                        return null;//hide item
                    else
                        return "Default";
                ;

            ).on('select2:close', function (evt) 
                window.Select2FilterFunc = function (state)  return "Default" ;
            );

        );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>

<select id="select1" class="js-states form-control" style="width:300px" multiple="multiple ">
        <optgroup label="Alaskan/Hawaiian Time Zone">
            <option value="AK" title="11111111">Alaska</option>
            <option value="HI" title="2222">Hawaii </option>
        </optgroup>
        <optgroup label="Pacific Time Zone">
            <option value="CA">California</option>
            <option value="NV">Nevada</option>
            <option value="OR">Oregon</option>
            <option value="WA">Washington</option>
        </optgroup>
        <optgroup label="Mountain Time Zone">
            <option value="AZ">Arizona</option>
            <option value="CO">Colorado</option>
            <option value="ID">Idaho</option>
            <option value="MT">Montana</option>
            <option value="NE">Nebraska</option>
            <option value="NM">New Mexico</option>
            <option value="ND">North Dakota</option>
            <option value="UT">Utah</option>
            <option value="WY">Wyoming</option>
        </optgroup>
        <optgroup label="Central Time Zone">
            <option value="AL">Alabama</option>
            <option value="AR">Arkansas</option>
            <option value="IL">Illinois</option>
            <option value="IA">Iowa</option>
            <option value="KS">Kansas</option>
            <option value="KY">Kentucky</option>
            <option value="LA">Louisiana</option>
            <option value="MN">Minnesota</option>
            <option value="MS">Mississippi</option>
            <option value="MO">Missouri</option>
            <option value="OK">Oklahoma</option>
            <option value="SD">South Dakota</option>
            <option value="TX">Texas</option>
            <option value="TN">Tennessee</option>
            <option value="WI">Wisconsin</option>
        </optgroup>
        <optgroup label="Eastern Time Zone">
            <option value="CT">Connecticut</option>
            <option value="DE">Delaware</option>
            <option value="FL">Florida</option>
            <option value="GA">Georgia</option>
            <option value="IN">Indiana</option>
            <option value="ME">Maine</option>
            <option value="MD">Maryland</option>
            <option value="MA">Massachusetts</option>
            <option value="MI">Michigan</option>
            <option value="NH">New Hampshire</option>
            <option value="NJ">New Jersey</option>
            <option value="NY">New York</option>
            <option value="NC">North Carolina</option>
            <option value="OH">Ohio</option>
            <option value="PA">Pennsylvania</option>
            <option value="RI">Rhode Island</option>
            <option value="SC">South Carolina</option>
            <option value="VT">Vermont</option>
            <option value="VA">Virginia</option>
            <option value="WV">West Virginia</option>
        </optgroup>
    </select>

【讨论】:

您的回答似乎没有回答问题。在您的示例中,您没有使用 之外的任何选项分组/分类。如何根据 2 个或更多分类参数过滤列表?

以上是关于如何根据选项类动态过滤 select2 列表的主要内容,如果未能解决你的问题,请参考以下文章

Select2 从过滤列表中选择所有选项以进行多项选择

如何将模型数据加载到在 Yii 中使用 Ajax 过滤的 Select2 下拉列表

使用格式动态设置 select2 选项

无法使用 Select2 以编程方式选择选项

Select2.js v4.0:如何将过滤文本传输到ajax源数据?

Yii2:Gridview过滤器中的kartik\Select2下拉列表