使用createSearchChoice的Select2使用新创建的键盘输入选项,即使给出匹配,错误或我错过了什么?

时间:2013-05-17 09:48:27

标签: jquery-select2

我正在使用Select2(版本3.4.0)来填充标记列表。标签通过ajax调用与现有标签匹配,我使用createSearchChoice来创建新标签。代码到目前为止工作,看起来像这样:

$(mytags).select2({
    multiple: true,
    placeholder: "Please enter tags",
    tokenSeparators: [ "," ],
    ajax: {
        multiple: true,
        url: myurl,
        dataType: "json",
        data: function(term, page) {
            return {
                q: term
            };
        },
        results: function(data, page) {
            return data;
        }
    },
    createSearchChoice: function(term) {
        return {
            id: term,
            text: term + ' (new)'
        };
    },
});

完全标准,但请注意(new)中附加的createSearchChoice。我需要用户知道这不是预先存在的标签。

它按预期工作:如果我开始输入“new-tag”,我会在列表顶部显示“new-tag(new)”标签,如果我选择它,则标签列表包含“new- tag- tag(new)“,如预期的那样。如果标签已存在,则Select2检测到匹配,并且不会创建“(新)”选项。按返回或单击匹配按预期工作。

在匹配时输入逗号(我的单个tokenSeparators条目)时会出现问题。 Select2关闭该标记,并将标记添加到列表中,但附加了“(new)”标签,即它使用createSeachChoice的返回值,即使它没有。{/ p>

这是Select2中的错误,还是我使用错了(我应该怎么做)?

3 个答案:

答案 0 :(得分:16)

我不确定这是不是一个错误 - 无论如何,目前GitHub问题跟踪器上没有涉及此行为的公开问题。

你可以自己解决这个问题。我们的想法是createSearchChoice回调必须能够判断term是否引用了搜索结果。但createSearchChoice无法直接访问搜索结果,那么我们如何才能启用?好吧,通过从results回调中保存最新一批搜索结果。

var lastResults = [];

$(...).select2({
    ajax: {
        multiple: true,
        url: "/echo/json/",
        dataType: "json",
        type: "POST",
        data: function (term, page) {
            return {
                json: JSON.stringify({results: [{id: "foo", text:"foo"},{id:"bar", text:"bar"}]}),
                q: term
            };
        },
        results: function (data, page) {
            lastResults = data.results;
            return data;
        }
    },
    createSearchChoice: function (term) {
        if(lastResults.some(function(r) { return r.text == term })) {
            return { id: term, text: term };
        }
        else {
            return { id: term, text: term + " (new)" };
        }
    }
});

此代码使用Array.some,因此您需要比IE8(这是select2最低要求)更好的运行它,但当然可以模拟行为。

<强> See it in action

但美中不足之处:只有当已经收到与当前搜索词相对应的搜索结果时,此代码才能正常运行

这应该是显而易见的:如果您输入非常快并创建一个与现有标签相对应的搜索字词,但在包含该标记的搜索结果到达之前点击逗号,则createSearchChoice将测试该标记的存在在先前收到的搜索结果中。如果这些结果包含标记,则标记将显示为“新”,即使它不是。

不幸的是,我不相信你可以采取任何措施来防止这种情况发生。

答案 1 :(得分:5)

我认为最好在服务器端工作,而不是推送结果。

如果服务器找不到标签,则返回带有新标签的json答案

{"more":false,"results":[{"id":"whatever","text":"new-tag (new)"}]}

答案 2 :(得分:2)

&#39; createSearchChoice&#39;还有另一个参数。 - &#39;页面&#39;,它列出了所有选项,您可以轻松找到它的傻瓜。

createSearchChoice = function (term, page) {
    if( page.some(function(item) {
        return item.text.toLowerCase() === term.toLowerCase();
    }) ){
        return { val: term, name: term + '*' };
    }
}