インクリメンタルサーチちょっと復習
1.データ受け渡しの準備
①ルーテイングを作る。今回は割愛。
②コントローラーで
def index
respond_to do |format|
format.html
format.json
end
end
ちなみにhtmlやjsonの後ろに{}内で処理を書いてあげると別のページに飛んでもらったりできるが、特に何も書かなければrailsのデフォルトのviewファイルへ、という感じっぽい
json.array! @users do |user|
json.id user.id
json.name user.name
end
としてjson形式で値を渡す
2テキストフィールドに入力されるたびにイベントが発火するように準備
$(function() { $("#インプットフォームのid名").on("keyup", function() { let input = $("#インプットフォームのid名").val(); console.log(input); }); });
console.logは仮置き
keyを離すたびにフォーム部分の値を.val();が取得している
3イベント時に非同期通信できるようにする
①jsファイル内
$(function() { $("#インプットフォームのid名").on("keyup", function() { let input = $("#インプットフォームのid名").val(); $.ajax({ type: "GET", url: "/users", data: { keyword: input }, dataType: "json" }) .done(function(users) { console.log("成功です"); }) .fail(function() { console.log("失敗です"); }); }); });
ajaxの形式を指定する。ここはもう少し後で追記するかも。
成功時と失敗時の処理を書く。今回は仮置き。
②usersコントローラー内
whereを使って曖昧検索し、@usersにログイン中のユーザー以外でキーワードの文字を含むユーザーを格納する。whereの曖昧検索については次のサイトが分かり易いが、とりあえず
モデルクラス.where("列名 LIKE ?", "%値%")
で0文字以上の任意の文字列を含む物を配列形式で全て取得できる。
参照元https://www.sejuku.net/blog/71189
def index return nil if params[:keyword] == "" @users = User.where(['name LIKE ?', "%#{params[:keyword]}%"] ).where.not(id: current_user.id).limit(10) respond_to do |format| format.html format.json end end
params[:keyword]は先にajax関数でdata{keyword: input}としたkeywordでinputはテキストフィールドの値を取得して変数に格納しておいた物。キーワードが空だったらnilを返す。
4JSファイル内
非同期通信の結果をもらって、htmlを作成する
①html組み立て用の関数を場合わけして作っておく
$(function(){
function addUser(user){
let html = `
<div class="json_output_field">
ユーザーがいた場合にテンプレートリテラル内で式展開できる${}を使い、必要な情報
を描画する。例: ${user.name}。
</div>
`
$("上で組んだhtmlをくっつける場所のid名とか").append(html);
}
function addNoUser(){
let html = `
<div>ユーザーが見つかりません的なhtml組み立てる</div>
`
$("上で組んだhtmlをくっつける場所のid名とか").append(html);
}
});
②2で作ったkeyup時に発火するイベント内に通信成功時と失敗時の処理を書く
$("検索フィールドのid名").on("keyup", function() { let input = $("検索フィールドのid名").val(); $.ajax({ type: "GET", url: "/users", data: { keyword: input }, dataType: "json" }) .done(function(users) { $("検索結果表示場所のid名").empty(); if (users.length !== 0) { users.forEach(function(user) { addUser(user); }); } else if (input.length == 0) { return false; } else { addNoUser(); } }) .fail(function() { alert("通信エラーです。ユーザーが表示できません。"); }); });
.failは説明要らないと思う
.doneでは前の検索結果が残ってしまわないように検索結果を表示する箇所をまず空にするために.empty()を使う。もし曖昧検索の結果受け取った配列usersが空でなければusersの各要素をuserとして扱い、addUser関数を使って表示用のhtmlを組み立てる。入力欄が空ならfalseを返し、入力があるにも関わらず該当ユーザーがいない(usersが空)の場合はユーザーが見つかりません的なhtmlを表示する。
補足doneが受け取ってるusers
keyupイベントでinputしてもらい、それをkeywordとして該当するユーザーをwhereで見つけて@usersに入れて1で作ったjbuilderで@usersを配列として扱いそれぞれのカラムが何に該当するかまで記述していた。なのでこのusersはコントローラー内での@usersということでいいだろう。実際htmlを組み立てる際は${user.name},${user.id}といったjbuilder内でしっかり渡した値を使っているので。というかjsファイル内の関数の引数名はあくまでその関数内での処理名で、元の名前はあんま関係無い感じか。外と関係あるのはkeyupみたいな元々決まってる名前かajax関数内の記述くらいなんかな。
この辺りの流れについて後日振り返ったので、そっちの方が流れの理解にはいいかも。ただこっちで書いた物を参考に端折って書いたのでこっちのメモはこっちのメモで必要なんで残しとく。