ユーザビリティ向上テーマでオートコンプリート機能は重要だとは考えていましたが、サーバ側への負荷などを考えると二の足を踏んでいました。
今回はリクエストまでの待機時間(入力開始から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" />
いやー、これ、使っててメチャ便利やんて思いました。
早く実装してれば良かったかな ^^;