ユーザビリティ向上テーマでオートコンプリート機能は重要だとは考えていましたが、サーバ側への負荷などを考えると二の足を踏んでいました。
今回はリクエストまでの待機時間(入力開始から2秒間は要求を出さない)や入力文字数制限(2文字以上タイプが無いと要求を出さない)といった制限を設けることで悩みを解消しました。
色々とやり方はあるようですが、typeaheadとBloodhoundの組み合わせを使いました。
理由は特にないのですがBootstrap3を使ったケースで調べてたら、このパターンが多いようだったので採用しました。
以下がソースになります。
var bloodhound = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), queryTokenizer: Bloodhound.tokenizers.whitespace, rateLimitWait: 2000, remote: { url: "product/get_list.json", prepare: function(query, settings){ settings.type = "POST"; settings.data = "sess_param=" + sess_param + "&title=" + query; return settings; }, filter: function(response){ return $.map(response.records, function (item) { return { title: item.title, id: item.id }; }); } } }); bloodhound.initialize(); $('.typeahead').typeahead({ highlight: true, hint: true, minLength: 2, classNames: {} }, { name:'items', displayKey: 'title', source: bloodhound.ttAdapter() }).on("typeahead:selected typeahead:autocomplete", function(e, data) { var id = (e.currentTarget.id).split('-'); return $('#id_products' + '-' + id[1]).val(data.id); });
typeaheadのminLengthで入力文字数の制限を行います。
また、今回は複数レコードを登録する画面での実装だったため、候補が選択された場合のイベントを定義し、複数存在する名称入力欄のid属性から名称とIDを紐付し、該当するID入力欄にも値を設定しました。
BloodhoundのrateLimitWaitで待機時間を指定します。
外部APIに対してPOSTメソッドでデータを取得する場合は、remote.prepareにリクエストを指定してあげれば良いようです。
なお、リクエストクエリがJSON形式の場合は、併せて以下を指定します。
settings.contentType = "application/json; charset=UTF-8";
あとは、HTMLに以下のような感じでクラス指定すれば、全ての名称入力欄に対してオートコンプリートを実装する事ができました~♪
<input type="text" name="title_product" id="title_product_0" placeholder="Product Title" class="form-control typeahead" />
いやー、これ、使っててメチャ便利やんて思いました。
早く実装してれば良かったかな ^^;