javascript jquery select2 (4.0) ajax with templateResult 和 templateSelection

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30746917/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 12:39:47  来源:igfitidea点击:

jquery select2 (4.0) ajax with templateResult and templateSelection

javascriptjqueryajaxjquery-select2jquery-select2-4

提问by JJeff

My Select2 was working on 3.5 correctly..

我的 Select2 在 3.5 上正常工作..

Since upgrading to v4.0 (not "full" - and changing keywords/functions as needed), I have a weird problem where there are extra AJAX calls being made. However, the URL is not defined, so they generate 404 Not Found errors. The URL is https://localhost:8443/myapp/undefined

自从升级到 v4.0(不是“完整的” - 并根据需要更改关键字/函数)后,我遇到了一个奇怪的问题,即进行了额外的 AJAX 调用。但是,未定义 URL,因此它们会生成 404 Not Found 错误。URL 是https://localhost:8443/myapp/undefined

They seem to be related to the templateResult and templateSelection being present. If I comment them out, the select2 works correctly (but my data is not formatted).

它们似乎与存在的 templateResult 和 templateSelection 相关。如果我将它们注释掉,select2 将正常工作(但我的数据未格式化)。

With them not commented out, I get the mysterious/undefined AJAX call once at initialization, then one call is made when I click on the select box, then once for everycharacter I type (even if I set minimumInputLength). However, even with these bogus AJAX calls, my "real" ajax call will fire and return results (which are properly formatted by templateResult/templateSelection. I have tried with and without "escapeMarkup" with no difference in behavior.

由于它们没有被注释掉,我在初始化时收到了一次神秘/未定义的 AJAX 调用,然后当我单击选择框时进行一次调用,然后对我输入的每个字符进行一次调用(即使我设置了 minimumInputLength)。然而,即使使用这些虚假的 AJAX 调用,我的“真正的”ajax 调用也会触发并返回结果(这些结果由 templateResult/templateSelection 正确格式化。我尝试过使用和不使用“escapeMarkup”,行为没有区别。

What is triggering these bad AJAX calls and how can I stop them? (Because otherwise, it is working just fine)

是什么触发了这些错误的 AJAX 调用,我该如何阻止它们?(因为否则,它工作得很好)

Thanks in advance!

提前致谢!

EditHere is a full page that demonstrates the issue. The extra network calls are generated by the tag that I use in the formatResult function. But why is it returning the html when it should be in a "loading" state?

编辑这里是一个完整的页面,演示了这个问题。额外的网络调用由我在 formatResult 函数中使用的标签生成。但是为什么它应该处于“加载”状态时返回 html?

Well, it turns out that setting the "placeholder" causes the loading variable to not be set, thus the html is returned (with its ill-formed tag)

好吧,事实证明设置“占位符”会导致未设置加载变量,因此返回 html(带有格式错误的标签)

So if a placeholder is set, the templateResult and templateSelection should also check for an empty id..

因此,如果设置了占位符,templateResult 和 templateSelection 还应检查空 id..

if (result.id == "" || result.loading) return result.text;

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<title></title>

<link rel="stylesheet" href="${pageContext.request.contextPath}/lib/select2/dist/css/select2.css" />
</head>
<body>

<form id="organization_lookup_form" class="form-horizontal" >
<div>
    Select2 using placeholder <select id="search1" style="width:300px"></select>
</div>
<div style="padding-top:250px">
    Select2 WITHOUT placeholder <select id="search2" style="width:300px"></select>  
</div>
</form>

<script src="${pageContext.request.contextPath}/lib/jquery/dist/jquery.min.js"></script>
<script src="${pageContext.request.contextPath}/lib/select2/dist/js/select2.min.js"></script>
<script>
$(document).ready(function () {
      function formatResult (result){
          console.log('%o', result);
          if (result.loading) return result.text;
          var html = '<div>'+
                '<img src="' + result.image + '">' +
                '<h4>'+result.label+'</h4></div>';
          return html;
      };

      $('#search1').select2({
          placeholder: "Search...",
          ajax: {
              url: '/search',
              dataType: 'json',
              data: function (params, page) {
                  return {
                      term: params.term, // search term
                      page: page
                  };
              },
              processResults: function (data, page) {
                  return {results: data.results};
              },
              cache: true
          },
          templateResult : formatResult,
          templateSelection : formatResult,
          escapeMarkup: function(m) {
              // Do not escape HTML in the select options text
              return m;
           },
          minimumInputLength: 3
      });
      $('#search2').select2({
//        placeholder: "Search...",
          ajax: {
              url: '/search',
              dataType: 'json',
              data: function (params, page) {
                  return {
                      term: params.term, // search term
                      page: page
                  };
              },
              processResults: function (data, page) {
                  return {results: data.results};
              },
              cache: true
          },
          templateResult : formatResult,
          templateSelection : formatResult,
          escapeMarkup: function(m) {
              // Do not escape HTML in the select options text
              return m;
           },
          minimumInputLength: 3
      });
});
</script>

</body>
</html>

采纳答案by Kevin Brown

There are a couple of issues here that are probably leading to the requests that you are seeing.

这里有几个问题可能会导致您看到的请求。

  1. Select2 requires the textattribute on objects to point to a human-readable version of the option. This is used in the background for matching options as well as for accessibility purposes, so it's important to use it.
  2. You are only checking to see if the loadingoption is set, which works if you are only handling the "Searching..." text but doesn't work if anything else is being handled. I would recommend instead checking for the absence of the imageproperty, which appears to be what is undefinedin these cases.
  1. Select2 要求text对象上的属性指向该选项的人类可读版本。这在后台用于匹配选项以及可访问性目的,因此使用它很重要。
  2. 您只是检查loading是否设置了该选项,如果您只处理“正在搜索...”文本,则该选项有效,但如果正在处理其他任何内容则无效。我建议改为检查是否缺少该image属性,这似乎是undefined这些情况下的内容。

And to answer the specific questions you've asked

并回答您提出的具体问题

What is triggering these bad AJAX calls and how can I stop them?

是什么触发了这些错误的 AJAX 调用,我该如何阻止它们?

Select2 only triggers remote requests while searching, so any extra requests must be generated within your code. In your case, this was because you were trying to display an image in your results, but you weren't handling cases where the image doesn't actually exist on the object.

Select2 仅在搜索时触发远程请求,因此必须在您的代码中生成任何额外的请求。在您的情况下,这是因为您试图在结果中显示图像,但您没有处理对象上实际不存在图像的情况。

But why is it returning the html when it should be in a "loading" state?

但是为什么它应该处于“加载”状态时返回 html?

The templateResultmethod is used when formatting many of the notices displayed in results, including the "Searching..." message. This allows you to apply special formatting to these messages, but it also means that you need to handle them in your templating methods. Normally this shouldn't be an issue, as it defines the textproperty that is typically used to display the human readable version of the option, but it causes problems when this property is not being used.

templateResult方法用于格式化结果中显示的许多通知,包括“正在搜索...”消息。这允许您对这些消息应用特殊格式,但这也意味着您需要在模板方法中处理它们。通常这应该不是问题,因为它定义了text通常用于显示选项的人类可读版本的属性,但是当不使用该属性时会导致问题。

回答by Bastien Ho

Since version 4.0, the value of templateResultand templateSelectionare just "appened". This behavior is not documented.

自从4.0版本,价值templateResulttemplateSelection只是“appened”。这种行为没有记录。

So if you pass html, all tags are displayed.

因此,如果您传递 html,则会显示所有标签。

The workaround is to return a jQuery object :

解决方法是返回一个 jQuery 对象:

 function formatResult (result){
      console.log('%o', result);
      if (result.loading) return result.text;
      var html = '<div>'+
            '<img src="' + result.image + '">' +
            '<h4>'+result.label+'</h4></div>';
      //return html;
      return $(html);
  };