16

我正在使用 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(new )”,正如预期的那样。如果标签已经存在,Select2 会检测到匹配,并且不会创建“(新)”选择。按回车键或单击匹配项按预期工作。

当我tokenSeparators在匹配时键入逗号(我的单个条目)时会出现问题。Select2 关闭该标记,并将标签添加到列表中,但附加了“(新)”标签,即它使用返回值,createSeachChoice即使它不必这样做。

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

4

3 回答 3

17

我不确定这是否是一个错误——无论如何,目前在 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 最低要求)更好的东西来运行它,但当然可以模拟该行为。

看到它在行动

然而,美中不足的是:只有在已经收到与当前搜索词相对应的搜索结果时,此代码才能正常工作。

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

不幸的是,我认为您无法采取任何措施来防止这种情况发生。

于 2013-05-31T13:00:52.790 回答
5

我认为最好在服务器端工作,而不是对结果进行调整。

如果服务器没有找到标签,让它返回一个带有新标签的 json 答案

{"more":false,"results":[{"id":"whatever","text":"new-tag (new)"}]}
于 2014-02-24T16:08:37.813 回答
2

'createSearchChoice'还有一个参数——'page',它列出了所有的选项,你可以很容易地用它找到骗子。

createSearchChoice = function (term, page) {
    if( page.some(function(item) {
        return item.text.toLowerCase() === term.toLowerCase();
    }) ){
        return { val: term, name: term + '*' };
    }
}
于 2014-10-16T14:45:34.540 回答