【问题标题】:Select2 dropdown but allow new values by user?Select2 下拉菜单但允许用户输入新值?
【发布时间】:2013-01-29 06:35:53
【问题描述】:

我希望有一个包含一组值的下拉列表,但也允许用户“选择”一个未在此处列出的新值。

如果您在tags 模式下使用它,我看到select2 支持此功能,但有没有不使用标签的方法?

【问题讨论】:

  • Select2 从来没有为我工作过,至少 createSearchChoice 在 4.0.3 中从来没有为我工作过,而且我不希望我的用户等待 ajax 完成才能返回相同的关键字,所以我不得不滚动出我自己的图书馆,我只是分享它,因为我认为它可能会帮助其他仍然像我一样困惑的人,如果您不同意我的回答,请不要投反对票:github.com/razzbee/tagcomplete

标签: jquery-select2


【解决方案1】:

@fmpwizard 提供的excellent answer 适用于 Select2 3.5.2 及以下版本,但不适用于 4.0.0

从很早开始(但可能不会早于这个问题),Select2 就支持“标记”:如果您允许,用户可以在其中添加自己的价值。这可以通过tags 选项启用,您可以使用an example in the documentation

$("select").select2({
  tags: true
});

默认情况下,这将创建一个与他们输入的搜索词具有相同文本的选项。如果您希望以特殊方式对其进行标记,则可以修改使用的对象,或者在选择对象后远程创建该对象。

$("select").select2({
  tags: true,
  createTag: function (params) {
    return {
      id: params.term,
      text: params.term,
      newOption: true
    }
  }
});

除了作为通过select2:select 事件传入的对象上易于发现的标志之外,额外的属性还允许您在结果中呈现稍有不同的选项。因此,如果您想通过在其旁边放置“(new)”来直观地表明这是一个新选项,您可以这样做。

$("select").select2({
  tags: true,
  createTag: function (params) {
    return {
      id: params.term,
      text: params.term,
      newOption: true
    }
  },
  templateResult: function (data) {
    var $result = $("<span></span>");

    $result.text(data.text);

    if (data.newOption) {
      $result.append(" <em>(new)</em>");
    }

    return $result;
  }
});

【讨论】:

  • 这对@Markus1980Wien 很有帮助
  • 这个sn-p我好像用过很多次了。
  • 如果不工作,请仔细检查您是否在 select2 上添加了此选项,而不是添加 ajax 选项。对于select2 ajax
  • 它在版本 select2 (4.0.6) 中的工作方式是这样的: $("select").select2({ tags: true, createTag: function (params) { return { id: params.term , text: params.term, newOption: true } }, templateResult: function (data) { var result = data.text; if (data.newOption) { result = result + '(new)'; } return result; } } );谢谢@Kevin Brown
  • 这应该是最重要的响应。我已经为此搜索了一段时间,这个选项回答了我在该主题上看到的所有问题。
【解决方案2】:

对于版本 4+,请查看下方的 this answerKevin Brown

在 Select2 3.5.2 及以下版本中,您可以使用类似:

$(selector).select2({
  minimumInputLength:1,
  "ajax": {
    data:function (term, page) {
      return { term:term, page:page };
    },
    dataType:"json",
    quietMillis:100,
    results: function (data, page) {
      return {results: data.results};
    },
    "url": url
  },
  id: function(object) {
    return object.text;
  },
  //Allow manually entered text in drop down.
  createSearchChoice:function(term, data) {
    if ( $(data).filter( function() {
      return this.text.localeCompare(term)===0;
    }).length===0) {
      return {id:term, text:term};
    }
  },
});

(取自 select2 邮件列表上的答案,但现在找不到链接)

【讨论】:

  • 很抱歉回复晚了,但非常感谢您的解决方案!另一张海报,发布了一个链接到你的要点顺便说一句,这让你加倍棒! :)
  • rrauenza 真棒,正是我要找的东西
  • 添加selectOnBlur: true 即可完成这项工作,请参阅:stackoverflow.com/questions/25616520/…
  • 提醒未来的读者,您可能希望同时使用tags: []createSearchChoice
  • 上面链接的小提琴似乎坏了。
【解决方案3】:

只是为了保持代码有效,我从his comment 发布@rrauenza Fiddle's code

HTML

<input type='hidden' id='tags' style='width:300px'/>

jQuery

$("#tags").select2({
    createSearchChoice:function(term, data) { 
        if ($(data).filter(function() { 
            return this.text.localeCompare(term)===0; 
        }).length===0) 
        {return {id:term, text:term};} 
    },
    multiple: false,
    data: [{id: 0, text: 'story'},{id: 1, text: 'bug'},{id: 2, text: 'task'}]
});

【讨论】:

  • 我使用了小提琴,但它在 Chrome 中似乎对我不起作用。你能确认一下吗?
  • @IcedD​​ante 代码正在运行。小提琴中的重点只是展示应该如何完成(选择隐藏在小提琴中)
  • 当我去小提琴时,我在任何地方都看不到 select2 下拉菜单。有一个实际...做某事的例子不是很好吗?
  • 如何设置外部数据?我的意思是,如果我想加载选定国家/地区的城市,而选定国家/地区本身就是一个下拉菜单,该怎么办?
【解决方案4】:

由于其中许多答案在 4.0+ 中不起作用,如果您使用 ajax,您可以让服务器添加新值作为选项。所以它会像这样工作:

  1. 用户搜索值(向服务器发出 ajax 请求)
  2. 如果发现值很好,则返回该选项。如果不只是让服务器像这样附加该选项:[{"text":" my NEW option)","id":"0"}]
  3. 提交表单后,只需检查该选项是否在数据库中,如果没有,请在保存前创建它。

【讨论】:

    【解决方案5】:

    我认为现在有更好的解决方案

    只需在选择选项上将标记设置为 true 吗?

    tags: true
    

    来自https://select2.org/tagging

    【讨论】:

      【解决方案6】:

      改进@fmpwizard 答案:

      //Allow manually entered text in drop down.
      createSearchChoice:function(term, data) {
        if ( $(data).filter( function() {
          return term.localeCompare(this.text)===0; //even if the this.text is undefined it works
        }).length===0) {
          return {id:term, text:term};
        }
      },
      
      //solution to this error: Uncaught TypeError: Cannot read property 'localeCompare' of undefined
      

      【讨论】:

      • 我使用了这个稍作修改我会在一秒钟内提出我的答案,但谢谢。
      【解决方案7】:

      感谢大家的帮助,我在 Codeigniter 中使用了以下代码,我正在使用版本:select2 的 3.5.2。

      var results = [];
      var location_url = <?php echo json_encode(site_url('job/location')); ?>;
      $('.location_select').select2({
          ajax: {
              url: location_url,
              dataType: 'json',
              quietMillis: 100,
              data: function (term) {
                  return {
                      term: term
                  };
              },
              results: function (data) {
                  results = [];
                  $.each(data, function(index, item){
                      results.push({
                          id: item.location_id,
                          text: item.location_name
                      });
                  });
                  return {
                      results: results
                  };
              }
          },
          //Allow manually entered text in drop down.
          createSearchChoice:function(term, results) {
              if ($(results).filter( function() {
                  return term.localeCompare(this.text)===0; 
              }).length===0) {
                  return {id:term, text:term + ' [New]'};
              }
          },
      });
      

      【讨论】:

      • 我真的真的不想使用ajax,这只会导致问题并导致我通过添加删除选项来做更多的工作。为什么这么难。他们所要做的就是添加“如果没有找到值,请不要清除文本字段”
      • 什么样的问题?使用 Ajax 已经 10 多年了,似乎从来没有给我带来过它给自己带来的同样程度的警报或担忧,也许你可以详细说明一下?
      • 是的,我将面临的问题是事实,例如用户输入了错误的值,然后该值已经发送到服务器以添加到数据库中。现在您需要浪费一个 restfull 调用并添加额外的 15 分钟的工作来解决这个问题(通过向服务器发送另一个 restfull 调用告诉它删除这个值)。当您将所有内容保留在客户端直到用户发布表单时,就不会发生这种情况。我最终只使用了标签,我不想这样做,因为它与我给客户的设计不是 100% 准确的。
      • add an extra 15 min of work - 哇,你一定有一些廉价的客户或项目,你无法证明 15 分钟的额外工作是合理的。
      • 不,这不是重点。当然,如果有必要,我会加 15 分钟,我的意思是我现在必须加。现在的另一个问题是设计被妥协了......除此之外,我的意思是如果这样的选项就在那里,它可以完全避免,但似乎他们特意不添加它。这就是为什么我觉得它令人沮丧......
      【解决方案8】:

      我刚刚从 Kevin Brown 那里偶然发现了这个。 https://stackoverflow.com/a/30019966/112680

      对于v4.0.6,您只需使用tags: true 参数即可。

      【讨论】:

      • 如果要保持文本框的格式怎么办?
      • 对不起,不知道答案。太久了,我目前没有使用它。
      【解决方案9】:
      var text = 'New York Mills';
      var term = 'new york mills';
      return text.localeCompare(term)===0;
      

      在大多数情况下,我们需要将值与不敏感的寄存器进行比较。而且这段代码会返回false,这会导致在数据库中创建重复记录。而且浏览器Safary不支持String.prototype.localeCompare(),这段代码在这个浏览器中不起作用;

      return this.text.localeCompare(term)===0;
      

      会更好地替换为

      return this.text.toLowerCase() === term.toLowerCase();
      

      【讨论】:

        猜你喜欢
        • 2013-01-12
        • 2014-10-26
        • 2016-04-01
        • 2016-06-19
        • 1970-01-01
        • 2012-07-17
        • 2011-03-13
        • 1970-01-01
        相关资源
        最近更新 更多