流れ
⑴ルーティングなどAPI側の準備をする
⑵テキストフィールドを作成する
⑶テキストフィールドに入力されるたびにイベントが発火するようにする
⑷イベント時に非同期通信できるようにする
⑸非同期通信の結果を得て、HTMLを作成する
⑹作成したHTMLをビュー上に追加する
⑺エラー時の処理を行う
⑻追加ボタンが押された時にイベントが発火するようにする
⑼追加ボタンをクリックされたユーザーの名前を、チャットメンバーの部分に追加し、検索結果からは消す
⑽削除を押すと、チャットメンバーから削除される
11ログイン中のユーザーを追加済みの状態にする
12編集画面では既存のユーザーが追加済みの状態にする
⑴ルーティングなどAPI側の準備をする
routes.rbでusers#indexのルーティングを設定する。
users_controller.rbにindexアクションを追加する。
JSON形式のレスポンスを返せるようにコントローラーに設定する
users_controllers.rb
def index
#検索した条件に当てはまるユーザーを@usersに代入
@users = User.search(params[:keyword], current_user.id)
#htmlとjsonで処理を分ける
respond_to do |format|
format.html
format.json
end
end
index.json.jbuilder
#@usersを配列形式にし、変数userとして分解していく
json.array! @users do |user|
json.id user.id
json.name user.name
end
#これにより、jsファイル上で、usersという配列、id、nameという変数が使えるようになる
⑵テキストフィールドを作成する
僕の場合は_form.html.hamlに記載
⑶テキストフィールドに入力されるたびにイベントが発火するようにする
users.js
$(function() {
//検索欄に文字入力されるたびに処理を行う
$("#user-search-field").on("keyup", function() {
//検索欄に入力された文字をvalで取得し変数inputに代入
let input = $("#user-search-field").val();
});
⑷イベント時に非同期通信できるようにする
ajaxの処理
users.js
$.ajax({
type: "GET", //httpメソッド(今回はget)
url: "/users", //送る先のurl
//keyを自分で決め(今回は"keyword"と定義)valueには先ほど検索欄から取得し代入したinputの値を使う
data: { keyword: input },
dataType: "json"
})
//ちゃんと動いているかを確認するために一時的にconsole.log
.done(function(users) {
console.log("成功です");
})
//ちゃんと動いているかを確認するために一時的にconsole.log
.fail(function() {
console.log("失敗です");
});
});
});
コントローラーの編集
users.controller.rb
def index
#キーワードがなければnilを返す
return nil if params[:keyword] == ""
#その文字を含むユーザーを探してきて、@usersに代入、ただしログインしている自分は除く。10人まで。
@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
⑸&⑹非同期通信の結果を得て、HTMLを作成しビュー上に追加する
done関数の処理
users.js
//jbuilderファイルで作った配列を引数にしdone関数を起動
.done(function(users) {
//if,else if,elseどの場合においても、処理後は、すでに検索欄に出力されている情報を削除する。
$("#user-search-result").empty();
//検索に一致するユーザーが0じゃない場合(いる場合)
if (users.length !== 0) {
//usersという配列をforEachで分解し、ユーザーごとにaddUser関数に飛ばす(処理は後ほど)
users.forEach(function(user) {
addUser(user);
});
//入力欄に文字が入力されてない場合処理を終了
} else if (input.length == 0) {
return false;
//検索に一致するユーザーがいない場合はaddNoUserに飛ばす
} else {
addNoUser();
}
})
引数に値が入っていた場合とそうじゃない場合のhtmlを生成し、それらをぶち込む
users.js
//一致するユーザーがいた場合の処理
function addUser(user) {
let html = `
<div class="chat-group-user clearfix">
<p class="chat-group-user__name">${user.name}</p>
<div class="user-search-add chat-group-user__btn chat-group-user__btn--add" data-user-id="${user.id}" data-user-name="${user.name}">追加</div>
</div>
`;
//作ったhtmlをぶち込む
$("#user-search-result").append(html);
}
//一致するユーザーがいなかった場合の処理
function addNoUser() {
let html = `
<div class="chat-group-user clearfix">
<p class="chat-group-user__name">ユーザーが見つかりません</p>
</div>
`;
//作ったhtmlをぶち込む
$("#user-search-result").append(html);
}
⑺エラー時の処理を行う
failの処理を記述
users.js
.fail(function() {
alert("通信エラーです。ユーザーが表示できません。");
});
⑻、⑼追加ボタンが押された時にクリックされたユーザーの名前を、チャットメンバーの部分に追加し、検索結果からは消す
users.js
//追加ボタンがクリックされた時の処理を記述する
$(document).on("click", ".chat-group-user__btn--add", function() {
//クリックされたところのデータを取得し各変数に代入
const userName = $(this).attr("data-user-name");
const userId = $(this).attr("data-user-id");
//クリックされたところのhtmlを親要素をごと消す(検索結果から消す)
$(this)
.parent()
.remove();
//削除ボタンの書いてあるhtmlを呼び出す処理に飛ばす
addDeleteUser(userName, userId);
//ユーザーをグループに登録するための処理
addMember(userId);
});
});
削除ボタンが押された時の処理
users.js
function addDeleteUser(name, id) {
let html = `
<div class="chat-group-user clearfix" id="${id}">
<p class="chat-group-user__name">${name}</p>
<div class="user-search-remove chat-group-user__btn chat-group-user__btn--remove js-remove-btn" data-user-id="${id}" data-user-name="${name}">削除</div>
</div>`;
//作ったhtmlをぶち込む
$(".js-add-user").append(html);
}
ユーザーをグループに登録するための処理
users.js
function addMember(userId) {
//userのidをinputタグの初期値としそれをnameを使ってgroupsコントローラ内のparamsで受け取る準備
let html = `<input value="${userId}" name="group[user_ids][]" type="hidden" id="group_user_ids_${userId}" />`;
//作ったinputタグをaddDeleteUser内で作ったhtml内にぶち込む
$(`#${userId}`).append(html);
}
⑽削除を押すと、チャットメンバーから削除される
users.js
$(document).on("click", ".chat-group-user__btn--remove", function() {
//クリックされたところのhtmlを親要素をごと消す(検索結果から消す)
$(this)
.parent()
.remove();
});
11 ログイン中のユーザーを追加済みの状態にする
_form.html.haml
%input{name: "group[user_ids][]", type: "hidden", value: current_user.id}
//ログインしているユーザーを取得し表示
%p.chat-group-user__name
= current_user.name
12編集画面では既存のユーザーが追加済みの状態にする
_form.html.haml
//そのグループに属するユーザーの配列をユーザーごとに分解する
- group.users.each do |user|
//もともと自分は表示されているので、それ以外のユーザーを表示
- if current_user.name != user.name
.chat-group-user.clearfix.js-chat-member
%input{name: "group[user_ids][]", type: "hidden", value: user.id}
%p.chat-group-user__name
= user.name
%a.user-search-remove.chat-group-user__btn.chat-group-user__btn--remove.js-remove-btn
削除