具有多个嵌套组的 Select2

Posted

技术标签:

【中文标题】具有多个嵌套组的 Select2【英文标题】:Select2 with multiple nested groups 【发布时间】:2014-11-26 14:48:53 【问题描述】:

我在将 Select2 与各种组一起使用时遇到了问题,只出现了后者。

<select name="txtConta" id="txtConta" data-placeholder="Selecione a conta">         
    <option value=""></option>
    <option value="S11892">2 - Gastos</option>
    <option value="S11893">2.1 - DESPESA OPERACIONAL FIXA</option>
    <option value="S11895">2.1.1 - PESSOAL</option>
    <option value="S11915">2.1.1.1 - GERENCIA/ADMINSTRATIVO</option>
    <option value="11916">2.1.1.1.1 - SAL&#193;Rios</option>
    <option value="11917">2.1.1.1.2 - DIVIDENDOS / COMISS&#213;ES /BONUS</option>
    <option value="11918">2.1.1.1.3 - INSS</option>
    <option value="11919">2.1.1.1.4 - FGTS</option>
    <option value="11920">2.1.1.1.5 - IRRF COD. 0561</option>
    <option value="11921">2.1.1.1.6 - PLANO DE SAUDE</option>
    <option value="11922">2.1.1.1.7 - TICKET REFEICAO</option>
    <option value="11923">2.1.1.1.8 - VALE TRANSPORTE</option>
    (...)
</select>

<script>
$('select').each(function () 
    $(this).select2(
        allowClear: true,
        width: 'resolve',
        dropdownAutoWidth: true
    );
);

$('#txtConta').find('option').each(function () 
    if ($(this).attr("value").indexOf('S') == 0) 
        $('<optGroup/>').attr('label', $(this).text()).appendTo($('#txtConta'));
        $(this).remove();
     else 
        $('#txtConta').find('optGroup').last().append($(this));
    
);
</script>

你可以在这个jsfiddle看到一个演示。

【问题讨论】:

【参考方案1】:

此解决方案使用 select2 4.0.1 版本进行了测试,您可以这样做:

    传递一个包含多个属性的数组(层次结构中每个节点的级别)。数组的结构很简单

    创建一个函数来格式化结果,即根据层次结构中的每个项目的级别看起来如何

    初始化select时,将创建的函数设置为属性templateResult

你可以在下面的代码中看到:

  $(document).on("ready", function() 
  var data = [
    id: "2",
    text: "2 - Gastos",
    level: 1
  , 
    id: "2.1",
    text: "2.1 - DESPESA OPERACIONAL FIXA",
    level: 2
  , 
    id: "2.1.1",
    text: "2.1.1 - PESSOAL",
    level: 3
  , 
    id: "2.1.1",
    text: "2.1.1 - PESSOAL",
    level: 4
  , 
    id: "2.1.1.1",
    text: "2.1.1.1 - GERENCIA/ADMINSTRATIVO",
    level: 4
  , 
    id: "2.1.1.1.1",
    text: "2.1.1.1.1 - SALÁRIOS",
    level: 5
  , 
    id: "2.1.1.1.2",
    text: "2.1.1.1.2 - DIVIDENDOS / COMISSÕES /BONUS",
    level: 5
  , 
    id: "2.1.1.1.3",
    text: "2.1.1.1.3 - INSS",
    level: 5
  , 
    id: "2.1.1.1.4",
    text: "2.1.1.1.4 - FGTS",
    level: 5
  ];

  function formatResult(node) 
    var $result = $('<span style="padding-left:' + (20 * node.level) + 'px;">' + node.text + '</span>');
    return $result;
  ;

  $("#mySelect").select2(
    placeholder: 'Select an option',
    width: "600px",
    data: data,
    formatSelection: function(item) 
      return item.text
    ,
    formatResult: function(item) 
      return item.text
    ,
    templateResult: formatResult,
  );
);
<!DOCTYPE html>

<html>

<head runat="server">
  <title></title>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2-rc.1/css/select2.min.css" rel="stylesheet" />
</head>

<body>
  <select id="mySelect">
  </select>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/js/select2.full.min.js"></script>
</body>
</html>

【讨论】:

嗨,我试过你的代码,它对我有用。但我有一个问题,列表没有排序。我该如何克服这个问题?? 如何设置选中的选项?? @amine 您可以使用插件 select2 设置选定的选项:$('#mySelect2').val('1'); // Select the option with a value of '1' $('#mySelect2').trigger('change'); // Notify any JS components that the value changed 请参阅select2.org/programmatic-control/add-select-clear-items【参考方案2】:

我是这样用的。工作正常。

$(document).on("ready", function() 
  function formatResult(node) 
    var level = 0;
    if(node.element !== undefined)
      level = (node.element.className);
      if(level.trim() !== '')
        level = (parseInt(level.match(/\d+/)[0]));
      
    
    var $result = $('<span style="padding-left:' + (20 * level) + 'px;">' + node.text + '</span>');
    return $result;
  ;

  $("#select2").select2(
    placeholder: 'Select an option',
    width: "300px",
    templateResult: formatResult,
  );
);
<!DOCTYPE html>

<html>

<head runat="server">
  <title></title>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
</head>

<body>
  <select id="select2" data-placeholder="Select an option" tabindex="-1" aria-hidden="true">
  <option></option>
  <optgroup label="Base">
    <option class="level_0" value="0">Base Parent</option>
  </optgroup>
  <option class="level_1" value="11">A</option>
  <option class="level_2" value="12">Ant</option>
  <option class="level_3" value="15">Fire Ant</option>
  <option class="level_2" value="14">Apple</option>
  <option class="level_1" value="13">B</option>
</select>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
</body>
</html>

【讨论】:

作品完美。如果您的数据源是 HTML 而不是 JSON,则很好的解决方案。【参考方案3】:

看看this GitHub issue。重要的是

HTML 本身禁止嵌套&lt;optgroup&gt;s,因此您的标记在到达 Select2 之前就无效了。但是,当您使用 JS 对象表示选项时,您可以通过子项任意嵌套选项。

这意味着您可以使用children 来获取多个嵌套选项。以下解决方案和jsfiddle基于fperie的solution。

<input name="txtConta" id="txtConta" data-placeholder="Selecione a conta" />     

<script>
var data = [
    id: "2", name: "2 - Gastos", children: [
        id: "2.1", name: "2.1 - DESPESA OPERACIONAL FIXA", children: [
            id: "2.1.1", name: "2.1.1 - PESSOAL", children: [
                id: "2.1.1", name: "2.1.1 - PESSOAL", 
                id: "2.1.1.1", name: "2.1.1.1 - GERENCIA/ADMINSTRATIVO", children: [
                    id: "2.1.1.1.1", name: "2.1.1.1.1 - SALÁRIOS",
                    id: "2.1.1.1.2", name: "2.1.1.1.2 - DIVIDENDOS / COMISSÕES /BONUS",
                    id: "2.1.1.1.3", name: "2.1.1.1.3 - INSS",
                    id: "2.1.1.1.4", name: "2.1.1.1.4 - FGTS"
                ]
            ]
        ]
    ]
    ];

$('#txtConta').select2(
    allowClear: true,
    width: 'resolve',
    dropdownAutoWidth: true,
    width: '400px',
    data: results: data, text: "name", 
    formatSelection: function(item)  
        return item.name 
    , 
    formatResult: function(item)  
        return item.name 
    
);
</script>

使用此解决方案,叶子仍然是可选的。如果您不想选择叶子,则应从叶子中删除 id 属性。

请参阅演示这两种配置的 JSfiddle。请注意,我只使用了您提供的部分数据。

【讨论】:

感谢回复,我的数据是通过数据库来的,所以下拉列表携带。我不明白我怎么能做到这一点。 好吧,您可以从数据库中检索数据并创建一个具有 Select2 所需格式的 JSON 对象,而不是仅仅回显 再次感谢您,我不具备执行此操作的 jQuery 知识,如果您有其他想法,我将不胜感激。拥抱 是否有可能去一个下拉列表并在这个结构中重新制作它? 你不需要 jQuery。如果您使用的是 php,您可以使用键 idnamechildren 创建一个多维数组,然后对数组执行 json_encode。你的 data 变量,在 javascript 中,将是 json_encode 的结果。我假设很多,因为我不知道你的整个过程。如果您愿意,我可以在您添加所有需求和代码(即查询数据库的代码)后,在 *** em Português 中提供完整的答案。【参考方案4】:

我尝试将此作为评论添加到上面 Saravanan 的帖子中,但评论的长度太长,因此请将此视为对他帖子的扩展,感谢他给我的想法。

这是我的一个 necro 帖子,但只是想扩展我如何使用 $document.ready 而不是 $document.on 的较新 jquery 格式实现上述解决方案。也稍作修改,因为我的嵌套在 pageLoad 中,因此该函数位于 pageLoad 之外,我使用的是属性而不是类。但重要的部分是,我必须同时使用 templateResult 和 templateSelection 才能工作,因为没有后者,什么都没有发生:

function pageLoad() 
    $(document).ready(function () 
        $(".multiple-group").select2(
            allowClear: true,
            closeOnSelect: false,
            templateResult: formatResult,
            templateSelection: formatResult
        );
    );    


function formatResult(node) 
    var level = 0;
    if (node.element !== undefined) 
        level = node.element.getAttribute("hierarchy-level");
        if (level.trim() !== '') 
            level = parseInt(level) - 1;
        
    

    var $result = $('<span style="padding-left:' + (15 * level) + 'px;">' + node.text + '</span>');
    return $result;

【讨论】:

以上是关于具有多个嵌套组的 Select2的主要内容,如果未能解决你的问题,请参考以下文章

如何在具有角度嵌套数据组的材料表中显示拆分标题

绘制多个组的嵌套分类值的折线图 (ggplot2)

每个日期/时间具有多个组的 MySQL 查询计数

绘制具有多个组的条形图

需要帮助使用局部变量减去具有多个组的前一行值

具有多个提要和组的 Mailchimp RSS 活动