【问题标题】:jQuery select2 with WordPress带有 WordPress 的 jQuery select2
【发布时间】:2022-01-21 22:39:46
【问题描述】:

我正在 WordPress 中使用 jQuery select2

我有一个这样的 HTML 表格。

如果用户点击Bob SMith and admin,我需要在这里,它将转换为带有多选的select2 下拉菜单。

但是当我点击它时,它看起来像下面

如果我再次点击,下拉菜单看起来像这样。

当我点击任何值时,如下所示

我的 jQuery 代码如下所示

(function($) {
  var states = [];
  
  $(document).ready(function() {
    $(".volunteer").on("click", function(event) {
      // Check if select is already loaded
      if (!$(this).has("select").length) {
        var cellEle = $(this);
        var cellId = this.id;

        // Populate select element
        cellEle.html(`<select class="js-example-basic-multiple" multiple="multiple">
            <option value="AL">Alabama</option>
            <option value="WY">Wyoming</option>
            </select>`);

        // Initialise select2
        let selectEle = cellEle.children("select").select2();
        
        if(states[cellId]){
            // preselect existing value
          selectEle.val(states[cellId]);
          selectEle.trigger('change'); 
        }

        selectEle.on("select2:close", function(event) {
          // Get selected value
          selectedValue = selectEle.select2('data')[0]['text'];

          // Update array          
          states[cellId] = selectedValue.id;
          
          // Destroy select2
          selectEle.select2('destroy');
          
          // Change html to just show the value
          cellEle.html(selectedValue.id);
        });
      }
    });
  });
})(jQuery)

我的 HTML 代码如下所示

<td class="volunteer" id="47">Bob SMith and admin</td>

【问题讨论】:

    标签: javascript jquery wordpress jquery-select2


    【解决方案1】:

    点击两次

    第一次单击单元格初始化 select2,第二次单击然后告诉 select2 显示下拉列表。如果只需要单击一次,您可以在 select2 初始化后调用https://select2.org/programmatic-control/methods 中描述的打开方法。

    // Initialise select2
    let selectEle = cellEle.children("select").select2();
    // Open the select2 dropdown
    selectEle.select2('open');
    

    替换选择

    当单击一个值 select2 被破坏时,.html() 调用应该用选定的值替换 select,但是它不能正常工作,因为存储的值上不存在 id 属性,这是导致单元格恢复为正常选择。

    处理"select2:close" 事件的代码包含selectedValue = selectEle.select2('data')[0]['text']; 行,它将第一个选定值[0] 的文本放入变量selectedValue。此后,单元格的 HTML 使用 cellEle.html(selectedValue.id); 更新,但此时 selectedValue 仅包含文本(例如“Alabama”),因此没有 .id 属性。为了解决这个问题,可以将 ID 和 Text 都存储在数组中,然后在需要的地方使用,例如:

    // Store the id and text of all selected values in the array
    selectedValue = selectEle.select2('data').map(function(value) {
      return { id: value.id, text: value.text }; 
    });
    
    // Get an array of IDs for the selected values (for preselecting values when select2 loads)
    selectEle.val(states[cellId].map(function(value) { return value.id })).trigger('change');
    
    // Get a comma separated string of the selected values (for populating the text in the cell)
    cellEle.html(states[cellId].map(function(value) { return value.text; }).join(','));
    

    多选模式 - 允许多项选择的示例是https://jsfiddle.net/aqgbxz1d/,并且也包含在下面的此答案中。这似乎是基于问题中的multiple="multiple" 属性的所需模式。

    示例已更新为不再使用select2:close 事件。相反,它使用change 事件来存储值更改,并在文档上使用第二个click 事件处理程序来在用户单击页面上的其他位置时破坏 select2 下拉列表。考虑到您要实现的目标,这似乎是一种更好的方法,因为它使选择处于打开状态以供选择多个值。

    单选模式 - 从 cmets 看来,可能需要单选模式。 https://jsfiddle.net/9jcnwbt2/1/ 是一个只允许选择的示例。如果需要单选模式,那么您需要:

    • 移除多重属性multiple="multiple"
    • 添加空白选项&lt;option&gt;&lt;/option&gt;
    • 您还可以复制文档单击事件中的代码,该事件会破坏 select2 并将 HTML 更新为更改事件。

    (function ($) {
      var states = [];
    
      $(document).ready(function () {
        $(".volunteer").on("click", function (e) {
          // Check if select is already loaded
          if (!$(this).has("select").length) {
            var cellEle = $(this);
            var cellId = this.id;
    
            // Populate select element
            cellEle.html(`<select class="js-example-basic" multiple="multiple">
                        <option value="AL">Alabama</option>
                        <option value="WY">Wyoming</option>
                        </select>`);
    
            // Initialise select2
            let selectEle = cellEle.children("select").select2({placeholder: "Select a value"});
    
            // Open the select dropdown so user doesn't have to click twice
            selectEle.select2('open');
    
            // Check if there is an existing value for this cell
            if (states[cellId]) {
              // preselect existing value
              selectEle.val(states[cellId].map(function (value) {
                return value.id
              })).trigger('change');
            }
    
            // Attach event handler to store value changes
            selectEle.on('change', function (e) {
    
              // Get selected values
              selectedValues = $(this).select2('data');
    
              // Update the states array with id and text of selected 
              // values. The id is needed to restore the values if select2
              // is reloaded on this cell. The text is required to generate
              // the replacement text shown in the cell
              states[cellId] = selectedValues.map(function (value) {
                return {
                  id: value.id,
                  text: value.text
                };
              });
            });
          }
    
          // Don't propagate the event
          // This prevents this document click handler from executing which would
          // remove select2 by calling destroy
          e.stopPropagation();
        });
      });
    
      // Attach event handler to document to capture any clicks
      // This will be triggered for all clicks on the page, except those 
      // captured by the method described above this prevents this firing
      // with e.stopPropagation()
      // Which this is called select2 on any cells must be destoryed and their 
      // text value populated
      $(document).on('click', function (e) {
        // Loop through all select2 elements
        $('.js-example-basic').each(function (idx) {
          // Get the ID of the cell that's been selected
          let cellId = $(this).parent().attr('id');
    
          // Destroy select2 on this element
          $(this).select2('destroy');
    
          // Change html on the parent element (td) to just show the value
          if(states[cellId] && states[cellId].length > 0){
            $(this).parent().html(states[cellId].map(function (value) {
              return value.text;
            }).join(','));
          } else {
            $(this).parent().html("Select a value...")
          }
        });
      });
    
    })(jQuery)
    .js-example-basic {
      width: 200px;  
    }
    
    thead{
        font-weight: bold;
    }
    
    table, th, td {
      border: 1px solid black;
    }
    
    tr {
      height: 36px;
    }
    
    td {
      width: 200px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
    
    <table>
      <thead>
        <tr>
          <td>Table Header 1</td>
          <td>Table Header 2</td>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="volunteer" id="47">Select a value...</td>
          <td class=""></td>
        </tr>
        <tr>
          <td class="volunteer" id="48">Select a value...</td>
          <td class=""></td>
        </tr>
      </tbody>
    </table>

    【讨论】:

    • 谢谢@Chris C。实际上我需要一个像i.stack.imgur.com/yxlTK.png 这样的预填充多值选择下拉菜单。
    • 屏幕截图似乎显示 select2 处于单选模式,而不是在示例代码中使用multiple="multiple" 启用的多选。这些模式显示在select2.org/getting-started/basic-usage。我已经更新了答案,修复了选择无值的错误,并提供了单选示例。
    • 谢谢@Chris C.
    • @abuabu 乐于助人。如果此答案或任何其他答案解决了您的问题,请将其标记为已接受。
    • 谢谢@Chris C。我接受了答案。
    猜你喜欢
    • 1970-01-01
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多