Help us understand the problem. What is going on with this article?

chat app.にてユーザー検索後、グループ追加を実装

はじめに・目的

インクリメンタルサーチ実装

1.API側準備

  • routing
routes.rb
resources :users, only: [:index]
  • users_controller.rbにindex定義
users_controllers.rb
class UsersController < ApplicationController
  def index
    respond_to do |format|
      format.html
      format.json
    end
  end
  • app/views/usersディレクトリにindex.json.jbuilderファイルを作成
index.json.jbuilder
json.array! @users do |user|
  json.id user.id
  json.name user.name
end

2.テキストフィールド作成

_form.html.haml
.chat-group-form__field
    .chat-group-form__field--left
      %label.chat-group-form__label{:for => "chat_group_チャットメンバーを追加"} チャットメンバーを追加
    .chat-group-form__field--right
      .chat-group-form__search.clearfix
        %input#user-search-field.chat-group-form__input{:placeholder => "追加したいユーザー名を入力してください", :type => "text"}/
      #user-search-result

  .chat-group-form__field.clearfix
    .chat-group-form__field--left
      %label.chat-group-form__label{:for => "chat_group_チャットメンバー"} チャットメンバー
    .chat-group-form__field--right
      #chat-group-users.js-add-user

3.テキストフィールドに入力するたび、イベント発火

users.js
$(function() {
  $("#user-search-field").on("keyup", function() {
    let input = $("#user-search-field").val();
    console.log(input);
  });
});

4.非同期通信ajax

users.js
  $("#user-search-field").on("keyup", function() {
    let input = $("#user-search-field").val();
    $.ajax({
      type: "GET",
      url: "/users",
      data: { keyword: input },
      dataType: "json"
    })
  });
});

5.入力値を曖昧検索する

users_controller.rb
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]に値が入っていればそのまま処理は続けられ、空だった場合はそこで処理が終わります。
検索処理の内容は、whereメソッドを使用し、入力された値を含むかつ、ログインしているユーザーのidは除外するという条件で取得しています。

6.非同期通信の結果を得て、HTMLを作成

users.js
$(function() {
  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>
    `;
    $("#user-search-result").append(html);
  }

  function addNoUser() {
    let html = `
      <div class="chat-group-user clearfix">
        <p class="chat-group-user__name">ユーザーが見つかりません</p>
      </div>
    `;
    $("#user-search-result").append(html);
  }
  $("#user-search-field").on("keyup", function() {
    let input = $("#user-search-field").val();
    $.ajax({
      type: "GET",
      url: "/users",
      data: { keyword: input },
      dataType: "json"
    })
      .done(function(users) {
        $("#user-search-result").empty();

        if (users.length !== 0) {
          users.forEach(function(user) {
            addUser(user);
          });
        } else if (input.length == 0) {
          return false;
        } else {
          addNoUser();
        }
      })
      .fail(function() {
        alert("通信エラーです。ユーザーが表示できません。");
      });
  });
});

メンバーの追加・削除機能の実装

1.追加ボタンが押された時にイベントが発火するようにする

users.js
$(document).on("click", ".chat-group-user__btn--add", function() {
  • $(document).onすることで常に最新のHTMLの情報を取得する

2.追加ボタンをクリックされたユーザーの名前を、チャットメンバーの部分に追加し、検索結果からは消す

まずは検索結果から名前を消す方法

users.js
$(document).on("click", ".chat-group-user__btn--add", function() {
    console.log
    const userName = $(this).attr("data-user-name");
    const userId = $(this).attr("data-user-id");
    $(this)
      .parent()
      .remove();
  • 「追加」ボタンがクリックされたユーザーが、検索結果一覧から消えるどのユーザーのhtmlかを特定するためにdata-user-iddata-user-nameを取得するため、対象であるユーザー情報を定数へ代入。
  • イベントが発生した要素を取得し、その親要素を削除
  • 今イベントが発生している追加ボタンのaタグを起点に、その親要素のchat-group-userを削除

次にメンバーをチャットメンバーに追加する

users.js
$(document).on("click", ".chat-group-user__btn--add", function() {
    console.log
    const userName = $(this).attr("data-user-name");
    const userId = $(this).attr("data-user-id");
    $(this)
      .parent()
      .remove();
    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>`;
    $(".js-add-user").append(html);
  }
  function addMember(userId) {        //DB上への追加
    let html = `<input value="${userId}" name="group[user_ids][]" type="hidden" id="group_user_ids_${userId}" />`;
    $(`#${userId}`).append(html);
  }

  • <input name='group[user_ids][]' type='hidden' value='ユーザーのid'> この記述により、userがDBに保存される

3.削除ボタンで、チャットメンバーから削除する機能を実装

users.js
$(document).on("click", ".chat-group-user__btn--remove", function() {
    $(this)
      .parent()
      .remove();
  });
  • .chat-group-user__btn--removeがクリックされたら、その親要素を削除。

4.ログイン中のユーザー(current_user)をチャットメンバーに表示し、他のメンバーを同じく表示する。

_form.html.haml
#chat-group-users.js-add-user
 .chat-group-user.clearfix.js-chat-member
   %input{name: "group[user_ids][]", type: "hidden", value: current_user.id}
   %p.chat-group-user__name= current_user.name
//current_user.idをgroup[user_ids]の配列に追加して、cuurent_user.nameを画面に表示

- 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
        削除
//user.nameと削除ボタンを全て表示

全体像

users.js
$(function() {
  var search_list = $("#user-search-result");

  function appendUser(user) {
    var 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>
              `;
    search_list.append(html);
  }
  function appendErrMsgToHTML() {
    var html = `
              <div class="chat-group-user clearfix">
                <p class="chat-group-user__name">ユーザーが見つかりません</p>
              </div>`;
    search_list.append(html);
  }
  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>
                `;
    $(".js-add-user").append(html);
  }
  function addMember(userId) {
    let html = `<input value="${userId}" name="group[user_ids][]" type="hidden" id="group_user_ids_${userId}" />`;
    $(`#${userId}`).append(html);
  }
  $(".chat-group-form__input").on("keyup", function(){
    var input = $(".chat-group-form__input").val();
    $.ajax({
      type: 'GET',
      url: '/users',
      data: { keyword: input },
      dataType: 'json'
    })
    .done(function(users) {
      search_list.empty();
      if (users.length !== 0) {
        users.forEach(function(user) {
          appendUser(user);
        });
      } else if (input.length == 0) {
        return false;
      } else {
        appendErrMsgToHTML();
      }
    })
    .fail(function() {
      alert('ユーザーが表示できません。');
    });
  });
  $(document).on('click','.chat-group-user__btn-add',function(){
    console.log
    const userName = $(this).attr("data-user-name");
    const userId = $(this).attr("data-user-id");
    $(this)
      .parent()
      .remove();
    addDeleteUser(userName, userId);
    addMember(userId);
  });
  $(document).on('click', '.chat-group-user__btn--remove', function(){
    $(this)
      .parent()
      .remove();
  });
});
Seungbaek_Seo
エンジニア見習い。学習備忘録。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした