##やりたいこと
USERSテーブル内のnameをtext_fieldから入力する際に、すでに入力済みのものが候補として出て来るようにする
##環境
Rails 5.1.5
Ruby ruby 2.3.5p376
#基本の流れ
参考サイトを元にjQuery UIで実装
とはいえ初心者過ぎてめちゃめちゃ悩んだので、実装の手順を追って段階的に記載していくことにします。
- gemインストール
- jQuery UIで予め用意した配列からサジェストを実装
- JSONファイルの出力と確認
- JSONのjQuery UIへの設定
- サジェストの実装
###jQuery UIのgemインストール
rails g scaffold user name
scaffoldしたデータでお試し実装。通常通り新規のユーザー入力ができることを確認の上、以下へ
gem 'jquery-ui-rails'
gem 'bootstrap-sass'
gem 'jquery-rails'
$ bundle
###jQueryの記述
まずはシンプルな形から。
無事RUN RONでサジェストがきく。
RUまで打つとRUNだけ候補に残る。
そもそもよく使うものがいくつかあって、その上で自由入力も、ならば此れでもいい気がする。
<%= form_with(model: user, local: true) do |form| %>
<!--バリデーションエラーの表示コード割愛-->
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, id: :user_name %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
<script>
$( function() {
var names = ['RON','RUN'];
$( "#user_name" ).autocomplete({
autoFocus: true,
source: names,
minLength: 0,
});
});
</script>
###JSONファイルの出力
すでに登録済みのDBから候補を表示させたいので、
一度出力したい内容をcontrollerで指定して出力、それを参照先とする。
一度便宜的にnewアクションに一緒にjsonファイルの出力埋め込んでみる
def new
@user = User.new
users = User.all
users = users.map(&:name)
render json: users.to_jsonend
respond_to do |format|
format.html
format.json { render json: users.to_json }
end
User.allで全てのユーザーを呼び出して、名前部分だけ取り出して配列化、それをJSONファイルとして受け渡し
respond_to ~ の記述がないと、newにアクセスしたときにjson画面に推移してしまうので、
末尾にjsonを指定したときだけjson画面に行けるようにアクセスしたURLのフォーマットに従って分岐させる
/users/new (既定値) → html
/users/new.json → json
new.jsonにアクセスしてみると、作成されたjsonファイルはこんな感じだった
[
"sasuke",
"akura",
"山田",
]
公式によると、value(選択決定後の表示)とlabel(サジェストしてる時の表示)の記述または配列がフォロー対象の模様
###JSONのjQuery UIへの設定
<script>
$( function() {
$( "#user_name" ).autocomplete({
autoFocus: true,
source: “/users/new.json”,
minLength: 0,
});
});
</script>
これで、候補一覧はでてくるが何を打っても同じものが出てくる状態になる。
参照はできているが絞込ができない
###サジェストの実装
コントローラーとルーティングの書き換え
新規にJSONファイル作成用のメソッドを作成する。
def auto_complete
users = User.select(:name).where("name like '%" + params[:term] + "%'").order(:name)
users = users.map(&:name)
render json: users.to_json
end
このURLにアクセスするためのルーティングも指定する
resources :users do
collection do
get ‘users/auto_complete’
end
end
jQueryで指定しているフォーム(この例だと text_filed (id=“user_name”))に入力した内容はminLengthなどの他の項目を満たす場合に、params[:term]としてsource先に定期的(初期値だと300ミリ秒)に送付されているため、それにともなって語句の絞込もおこなわれる模様。
<script>
$( function() {
$( "#user_name" ).autocomplete({
autoFocus: true,
source: "/users/auto_complete_name.json",
minLength: 1,
});
});
</script>
###ハマったポイント
-
sourceに記載する相対URLの頭の/が抜けていて指定ができなかった。
- 記載は source: “/users/auto_complete.json” など、頭は必ず/から。
-
controllerで配列化したものをViewに持ってきてそれを候補として使えない
- Viewにおいた地点でダブルクォーテーションが文字列化してしまいうまく動かない
-
JSONファイルを指定しているが、サジェストがきかない
- 公式に記載があった。絞込は外部ファイルの場合できないようなので、params[:term]を使って記載するべし
###感想
何はなくとも公式読んだほうがいい…
参考
公式:
https://api.jqueryui.com/autocomplete/#option-delay
Rails 5 Auto completeを実装してみた
https://qiita.com/swamp09/items/6fb852489b4dc3acfbdd
Ruby on Rails - Railscasts PRO #102 Auto-Complete Association (revised)
https://www.youtube.com/watch?v=M7yhPlIehFA
JS形式のレスポンスと remote: true を使う
https://qiita.com/hc_isobe/items/a29860d3e86a6bc5fd3e
JQueryで自動補完
https://qiita.com/yu_0105/items/20c4f52e71020af42e7b
AutoCompleteウィジェットで候補リストをサーバーサイドから取得するには?
https://www.buildinsider.net/web/jqueryuiref/0019
RailsでAjax基本形(Scaffoldで学ぶ)
https://qiita.com/mm36/items/684f36f22e79d0a27ae9
jqueryのメモ
https://elearn.jp/jmemo/tag/form