Select2下拉菜单,但允许用户输入新值吗?


125

我想要一个具有一组值的下拉菜单,但还希望用户“选择”未在此处列出的新值。

如果您在模式下使用select2,我看到它支持它tags,但是有没有办法不用标签来做到这一点?


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

Answers:


100

对于版本4+,请在下面通过Kevin 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邮件列表上的答案,但现在找不到链接)


4
对不起,您的回复很晚,但非常感谢您的解决方案!另一位张贴者张贴了您的要点btw的链接,这使您倍赞!:)
johnjohn

很棒的rrauenza,正是我想要的
Matthias S

4
添加selectOnBlur: true将做的工作,请参阅:stackoverflow.com/questions/25616520/...
阿里Fattahi

1
面向未来的读者,您可能想与tags: []一起使用createSearchChoice
凯文·布朗

5
上面链接的小提琴似乎坏了。
Wolfr '16

175

@fmpwizard提供的出色答案适用于Select2 3.5.2及更低版本,但不适用于4.0.0

自从很早(但可能还不早于这个问题)开始,Select2就支持“标记”:如果允许的话,用户可以在其中添加自己的值。可以通过tags选项启用此功能,您可以在文档中试用一个示例

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

默认情况下,这将创建一个选项,该选项的文本与输入的搜索词相同。如果要以特殊方式标记对象,则可以修改所使用的对象,也可以在选择对象后远程创建该对象。

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

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

$("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非常有帮助
abiieez

我想我已经多次使用了此代码段。
Sahu V Kumar

如果不起作用,请仔细检查,您已经在select2上添加了此选项,而没有在ajax选项中添加。for select2 ajax
Zohaib

2
通过以下方式,它在版本select2(4.0.6)中起作用:$(“ select”)。select2({标签:true,createTag:函数(参数){返回{id:params.term,文本:params.term,newOption :true}},templateResult:函数(数据){var result = data.text; if(data.newOption){result =结果+'(new)';}返回结果;}}); 感谢@Kevin Brown
M. Salah

这应该是最高的回应。我已经为此搜索了一段时间,该选项回答了我在该主题上看到的每个问题。
贾斯汀

14

为了使代码保持生命力,我从他的评论中发布@rrauenza Fiddle的代码

的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'}]
});

2
我去了小提琴,但它似乎不适用于Chrome。你可否确认?
IcedD​​ante 2015年

@IcedD​​ante代码正在工作。小提琴的要点只是为了显示应该如何做(选择隐藏在小提琴中)
Michel Ayres

4
当我去提琴时,我在任何地方都看不到select2下拉列表。有一个实际上可以做某事的例子不是很好吗?
IcedD​​ante 2015年

如何设置外部来源的数据?我的意思是,如果我想加载所选国家/地区的城市,而所选国家/地区本身就是下拉菜单,该怎么办?
阿里·拜格

12

由于许多答案在4.0+中均不起作用,因此,如果您使用的是Ajax,则可以让服务器将新值添加为选项。因此它将像这样工作:

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


4

@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

我对它进行了一些细微的修改,稍后我会给出答案,但谢谢。
2015年


1
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();

1

感谢您的帮助,我在Codeigniter II中使用下面的代码,使用的是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]'};
        }
    },
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.