1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Rails, jQ]インクリメンタルサーチ

1
Last updated at Posted at 2020-03-10

インクリメンタルサーチ

本記事では前回作成したユーザーの名前検索機能を使用して実装していきます。
以下を使用しています。

  • ruby 2.5.1
  • rails 5.2.4.1
  • gem 'jquery-rails'
  • gem 'devise'

なお、使用するビューは以下を使用します。

index.html.erb
<%= form_with(url: users_searches_path, local: true, method: :get, class: "search_form") do |f| %>
  <%= f.text_field :keyword, placeholder: "Name", class: "search_input" %>
  <%= f.submit "Search", class: "search_btn" %>

<div class="contents">
  <% @users.each do |user| %>
    <div class="user_content">
      <p class="user_name">
        user.name
      </p>
    </div>
  <% end %>
</div>

準備

以下が記入されていなければ記入します。

app/assets/javascripts/application.js
//= require jquery

フォーマット毎に処理を分ける

フォーマット毎に処理を分けるためコントローラーのindexアクションを編集します。

controllers/users/searches_controller.rb

  def index
    @users = User.search(params[:keyword])
    respond_to do |format|
      format.html
      format.json
    end
  end
``````
#### respond_to
アクションの中でHTMLとJSONなどのフォーマット毎にhtmlかjsonかを条件分岐することができます

### jbuilderファイルの作成、編集
index.json.jbuilderを新規作成し内容を編集します

`````app/views/tweets/searches/index.json.jbuilder
json.array! @users do |user|
  json.id user.id
  json.name name.name
end
`````
jbuilderという拡張子を持つテンプレートではJSONという名前のJbuilderオブジェクトが自動的に利用できるようになります
arrayメソッドはその内の一つでJavaScript側に配列で値を送ることができます

# search.jsの作成、編集

### 検索フォームの値を取得
`````app/assets/javascripts/search.js
$(function() {
  $(".search_input").on("keyup", function() {
    var input = $(".search_input").val();
  });
});
`````
keyupイベントを使用して文字が入力される度に発火するようにします

### JSON形式で値を返す

`````app/assets/javascripts/search.js
$(function() {
  $(".search_input").on("keyup", function() {
    var input = $(".search_input").val();
//---以下を追記---
    $.ajax({
      type: 'GET',
      url: '/users/searches',
      data: { keyword: input },
      dataType: 'json'
    })
//---以上を追記---
  });
});
`````
Ajax通信を実現するためには上記のように$.ajaxメソッドを使用します
また上記のコードは
HTTPメソッドはGETで/users/searchのURLに{ keyword: input }を送信サーバーから値を返す際はJSON
という意味を持ちますJSON形式の場合はapp/views/users/searches/index.json.jbuilderが読まれ,該当する投稿情報はjbuilderによってJSONに変換されてJavaScriptのファイルに返されます

### レスポンス結果によって処理を分ける
`````app/assets/javascripts/search.js
$(function() {
  $(".search_input").on("keyup", function() {
    var input = $(".search_input").val();
    $.ajax({
      type: 'GET',
      url: '/users/searches',
      data: { keyword: input },
      dataType: 'json'
    })
//---以下を追記---
    .done(function(users) {
      $(".contents").empty();
      if (users.length !== 0) {
        users.forEach(function(user){
          appendUser(user);
        });
      } else {
        appendErrMsgToHTML("一致するユーザーはいません");
      }
    })
    .fail(function() {
      alert('error');
    });
//---以上を追記---
  });
});
`````
レスポンスが成功した場合はユーザーが表示される親要素の中身を都度空っぽにしますそしてusersが空ではない場合usersの中身の数だけappendUser関数を呼び出します
該当ユーザーがいない場合は一致するツイートがありませんという引数を与えappendErrMsgToHTML関数を呼び出します
またレスポンスに失敗した場合はアラートを表示させます

#### empty()メソッド
指定したDOM要素の子要素のみを削除するメソッドです
指定したDOM要素自体を削除するremoveメソッドとは異なります

#### forEachメソッド
forEachは与えられた関数を配列に含まれる各要素に対して一度ずつ呼び出します

### 検索に該当ユーザーいた場合、いない場合の関数を定義

````app/assets/javascripts/search.js
$(function() {
//---以下を追記---
  var search_list = $(".contents");

  function appendUser(user) {
    var html = `
               <div class="user_content">
                 <p class="user_name">
                   #{user.name}
                 </p>
               </div>
               `
    search_list.append(html);
   }

  function appendErrMsgToHTML(msg) {
    var html = `
          <div class="user_content">
                  <p class="user_name">
                    ${ msg }
                  </p>
                 </div>
         `
    search_list.append(html);
  }
//---以上を追記---
  $(".search_input").on("keyup", function() {
    var input = $(".search_input").val();
    $.ajax({
      type: 'GET',
      url: '/users/search',
      data: { keyword: input },
      dataType: 'json'
    })
    .done(function(users) {
      search_list.empty();
      if (users.length !== 0) {
        users.forEach(function(user){
          appendUser(user);
        });
      } else {
        appendErrMsgToHTML("一致するユーザーはいません");
      }
    })
    .fail(function() {
      alert('error');
    });
  });
});
````
検索に該当ユーザーがいた場合
変数htmlにユーザー情報を表示する要素を代入しappendメソッドで親要素の一番下に追加します
検索に該当ユーザがいない場合
変数htmlに"一致するユーザーはいません"を表示する要素を代入しappendメソッドで親要素の一番下に追加します

# おわり
これでインクルメンタルサーチが実装できました
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?