web-dev-qa-db-ja.com

Select2とcreateSearchChoiceは、一致、バグ、または何か不足している場合でも、キーボード入力に新しく作成された選択肢を使用しますか?

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) in createSearchChoice。これが既存のタグではないことをユーザーに知らせてください。

期待どおりに機能します。「new-tag」と入力し始めると、リストの上部に「new-tag(new)」タグの候補が表示されます。選択すると、タグリストに「new-tag(new) )"、 予想通り。タグが既に存在する場合、Select2は一致を検出し、「(new)」の選択肢は作成されません。 Returnキーを押すか、試合をクリックすると、期待どおりに機能します。

一致しているときにカンマ(tokenSeparatorsの1つのエントリ)を入力すると、問題が発生します。 Select2はそのトークンを閉じ、タグをリストに追加しますが、「(new)」ラベルが追加されます。つまり、必要がない場合でも、createSeachChoiceからの戻り値を使用します。

これはSelect2のバグですか、それとも間違って使用していますか(代わりに何をすべきですか)?

16
Ben Deutsch

これがバグかどうかはわかりません。いずれにしても、現時点では、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はタグ内でのタグの存在をテストします以前に受け取った検索結果。これらの結果にタグが含まれていない場合、タグが含まれていない場合でも、タグは「新規」として表示されます。

残念ながら、これを防ぐためにできることはないと思います。

16
Jon

結果を調整する代わりに、サーバー側で作業する方が良いと思います。

サーバーがタグを見つけられない場合は、新しいタグでjson応答を返します

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

'createSearchChoice'-'page'には別のパラメーターがあり、すべての選択肢が一覧表示され、簡単にそれを見つけることができます。

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