web-dev-qa-db-ja.com

Select2ドロップダウンですが、ユーザーによる新しい値を許可しますか?

値のセットを含むドロップダウンが必要ですが、ユーザーはそこにリストされていない新しい値を「選択」することもできます。

tokensモードで使用している場合、 select2 がこれをサポートしていることがわかりますが、トークンを持たずにそれを行う方法はありますか?

113
johnjohn

バージョン4+の場合 この回答 以下 ケビンブラウン

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メーリングリストの回答から取得しましたが、現在リンクを見つけることができません)

93
fmpwizard

優秀な回答 によって提供される @ 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イベントを介して渡されたオブジェクトに簡単に見つけられるフラグとして機能することに加えて、追加のプロパティを使用すると、結果でオプションをわずかに異なるようにレンダリングできます。したがって、「(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;
  }
});
158
Kevin Brown

コードを有効に保つために、 @ rrauenza Fiddleのコード from his comment を投稿しています。

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'}]
});
14
Michel Ayres

これらの回答の多くは4.0以降では機能しないため、ajaxを使用している場合、サーバーに新しい値をオプションとして追加させることができます。したがって、次のように機能します。

  1. ユーザーが値を検索する(サーバーにajaxリクエストを行う)
  2. 値が優れている場合、オプションを返します。サーバーにこのオプションを追加するだけではない場合:[{"text":" my NEW option)","id":"0"}]
  3. フォームが送信されたら、そのオプションがデータベースにあるかどうかを確認し、保存されていない場合は作成します。
11
Eric

@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
4
Vikash Singh

今私が思うより良い解決策があります

選択オプションでタグ付けをtrueに設定するだけですか?

tags: true

from https://select2.org/tagging

3
Steven Moffat

私はケビン・ブラウンからこれにつまずいた。 https://stackoverflow.com/a/30019966/11268

v4.0.6に対して行う必要があるのは、tags: trueパラメーターを使用することだけです。

2
dbinott
var text = 'New York Mills';
var term = 'new york mills';
return text.localeCompare(term)===0;

ほとんどの場合、インセンシティブレジスタと値を比較する必要があります。また、このコードはfalseを返します。これにより、データベースに重複レコードが作成されます。さらに、String.prototype.localeCompare()はブラウザーSafaryではサポートされておらず、このコードはこのブラウザーでは機能しません。

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

に置き換えます

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

助けてくれてありがとう、私が使用しているCodeigniter内で以下のコードを使用しました。

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]'};
        }
    },
});
0
Sam