【问题标题】:Select2: Preselected item and correct rendering through templateSelectionSelect2:通过templateSelection预选item并正确渲染
【发布时间】:2017-07-13 12:15:42
【问题描述】:

使用Select2 v4 时,建议(实际上是正确的)方式以编程方式设置选定值,是操作底层选择元素,添加所需的<option> 元素,设置$selectElement.val(<value>) 的值并触发 .trigger('change') 事件,以便 select2 插件将从底层选择元素更新自身。你可以看到这个here

问题在于,当您定义了 templateSelection 时,它不仅返回所选值的文本,还返回整个 HTML DOM(例如,您可以应用样式、添加图像、图标等并返回作为呈现的选择)。

templateSelection 接受来自数组数据源或 ajax 数据源等的输入。每个项目代表一个选项,但它可能不仅仅是 idtexttemplateSelection 可能会考虑项目的许多属性来生成渲染输出。

您只能在<option> 元素中定义值和文本。您无法定义要设置为选中的实际对象(项目),以便templateSelection 可以产生正确的输出。

有没有办法只使用 select2 的 API 来实现?

如果没有,是否有任何其他解决方法可以通过templateSelection从正确呈现的代码中选择值?

【问题讨论】:

    标签: jquery jquery-select2


    【解决方案1】:

    以防万一像我这样的人遇到这种情况,Select2 v4 手册为此提供了答案:https://select2.org/programmatic-control/add-select-clear-items#preselecting-options-in-an-remotely-sourced-ajax-select2

    以下 sn-p 来自文档。本质上,您通过 ajax 调用获取初始值,并通过select2:select 事件以编程方式设置初始值。

    // Set up the Select2 control
    $('#mySelect2').select2({
        ajax: {
            url: '/api/students'
        }
    });
    
    // Fetch the preselected item, and add to the control
    var studentSelect = $('#mySelect2');
    $.ajax({
        type: 'GET',
        url: '/api/students/s/' + studentId
    }).then(function (data) {
        // create the option and append to Select2
        var option = new Option(data.full_name, data.id, true, true);
        studentSelect.append(option).trigger('change');
    
        // manually trigger the `select2:select` event
        studentSelect.trigger({
            type: 'select2:select',
            params: {
                data: data
            }
        });
    });
    

    但是,如果您使用 templateSelection 选项,并返回一个 jQuery 对象以提供花哨的单行格式选择结果,则此解决方案将不起作用。事实上,触发 select2:select 似乎什么也没做。

    使用 jQuery,我发现我可以将数据附加到选项,并从 templateSelection 函数中,将此数据用作后备。

    // create the option and append to Select2
    var option = new Option(data.full_name, data.id, true, true);
    $(option).data('raw', data);
    studentSelect.append(option).trigger('change')
    

    并且在templateSelection函数中:

    templateSelection: function (result) {
        if (!result.id || result.loading) {
            return result.text
        }
        var $container = $(
            '<div class="clearfix">' +
                '<div class="pull-left select2-result__name"></div>' +
                '<div class="pull-right select2-result__finding_name"></div>' +
            '</div>'
        );
    
        var raw = $(result.element).data('raw')
        $container.find('.select2-result__name').text(result.name || raw.name || result.text)
        $container.find('.select2-result__finding_name').text(result.finding_name_1 || raw.finding_name_1)
    
        return $container
    }
    

    此示例使用多个后备。我们总是尝试使用结果中的内容,就像在正常的 ajax 调用中提供的那样,但我们会退回到初始选项的原始数据,如果缺少,则退回到文本字段。

    【讨论】:

      【解决方案2】:

      templateSelection 是根据选项的文本内容构建对象的回调。返回并显示的对象与选项的内容不是一回事。选项保持简单的 id 和文本内容。样式单独处理。

      当您定义templateSelection 时,您定义了一个将选项作为参数的函数,因此您可以访问文本和选项的ID 作为可用变量。此函数将返回根据您的模板构建的对象。

      看这个例子:

      $(document).ready(function() {
        $('.js-example-basic-single').select2({
          width: 'width: 100%',
          templateSelection: formatState
        });
      });
      
      $('.js-example-basic-single').val('WY');
      $('.js-example-basic-single').trigger('change');
      
      function formatState(state) {
        console.log(state);
        var $state = $(
          '<span>Content from the template: ' + state.element.text + ' ' + state.element.value + '</span>'
        );
      
        return $state;
      }
      <script src="https://code.jquery.com/jquery-2.2.4.js"></script>
      <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
      <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
      <select class="js-example-basic-single" name="state">
        <option value="AL">Alabama</option>
        <option value="WY">Wyoming</option>
      </select>

      编辑:

      由于您可以访问状态,因此您可以访问使用动态数据定义的任何属性。而且您可以访问元素,因此您还可以拥有数据属性。这使您可以做一些更精细的事情:

      $(document).ready(function() {
        $('.js-example-basic-single').select2({
          width: 'width: 100%',
          templateSelection: formatState,
          data: [{
            id: 0,
            text: "Wyoming"
          }, {
            id: 1,
            text: "Alabama",
            selected: true,
            disabled: true,
          }, {
            id: 2,
            text: "Washington",
            selected: true,
            customProp: 'something'
          }]
        });
      });
      
      
      
      function formatState(state) {
        console.log(state);
        var $state 
        if (state.customProp) {
          $state = $(
            '<span>Content from the template: ' + state.element.text + ' ' + state.element.value + ' and my custom property is <strong>' + state.customProp + '</strong></span>'
          );
        } else {
        $state = $(
            '<span>Content from the template: ' + state.element.text + ' ' + state.element.value + '</span>'
             );
        }
      
        return $state;
      }
      <script src="https://code.jquery.com/jquery-2.2.4.js"></script>
      <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
      <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
      <select class="js-example-basic-single" name="state">
      </select>

      【讨论】:

      • 这就是重点,我需要更多的文本和值来呈现。我的项目是一个 JSON 对象,具有许多属性(活动、禁用、已售出、可用等)。我需要访问所有这些以呈现适当的 html
      • 我的问题是关于页面初始呈现时的预选值。当用户通过 UI 选择一个选项时,templateSelection 与实际项目状态配合得非常好。当数据源是js数组时也很好用。
      • 但是当数据源是ajax远程api时,我在第一次渲染页面时根本没有任何js项。用户必须单击选择元素,然后数据来自服务器并正确呈现选项。但是,如果我必须从一开始就必须使用已选择的项目呈现选择框,我就无法访问该状态。我只有一个 id 和一个来自我在 select 元素中呈现的选项的文本。
      【解决方案3】:

      我在使用 Select2 v4.0.3 时遇到了同样的问题。通过为当前选择项数组中的目标项添加必要的属性来解决它:

      var $widget = jQuery('#mySelect2Widget');
      
      // add new option to widget
      var newOption = new Option('New option text', 'New option id', false, true);
      $widget.append(newOption);
      
      // get current selection items
      var items = $widget.select2('data');
      var targetItem = null;
      
      // find newly added item in the array by id or smth else
      // and set it to the "targetItem" variable
      
      targetItem.prop1 = 'abc';
      targetItem.prop2 = 1;
      
      // trigger "change" event
      $widget.trigger('change');
      

      【讨论】:

      • 我没有 .select2('data') 数组。我的对象来自 ajax 源。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-22
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多