2
0

More than 1 year has passed since last update.

RailsでAjax通信を使って項目を絞り込む

Posted at

やりたいこと

 個人開発でやっているサービス「lytnote」の改善を行いたい。目標一覧画面にはユーザーが登録した目標が並んでいる。それぞれにはステータスがあって、完了や中止や進行中が選べる。振り返りの際に目標のステータスを変更するのだ。

目標A  状態:進行中
目標B  状態:完了
目標C  状態:中止
目標D  状態:完了
....

 でも使っていくと、目標がどんどん増えてしまう。進行中の目標のみを絞り込んで表示したい。

 目標の絞り込みを行うぞ。

フロー

目標一覧画面表示
↓
絞り込みたいステータスをプルダウンで選ぶ 
↓
絞り込みボタンを押す
↓
絞り込まれる

 これでやっていこう。つくるものを考える。

  1. 一覧画面にプルダウン表示
  2. コントローラー修正
  3. jsファイル修正
  4. 一覧画面に部分テンプレート追加

1. 一覧画面にプルダウン表示

app/views/plans/index.html.erb
<%# 略 %>

<%= form_with url: plans_path, method: :get, local: false do |f| %>
    <%= f.select :status, ["進行中","中止/完了","全て"] ,{class: "form-control"}%>
    <%= f.submit   "絞り込み" ,{class: "btn-primary"}%>
<% end %>

<%# 略 %>

local: false がポイントだ。これによってフォームの送信がAjaxで行われることになる。

2. コントローラー修正

Ajax通信になってもコントローラーのいく先は同じである。今回はindexアクションに飛ばすようにしている。ただ飛ばすだけでなく、プルダウンの中の値を確認し、それによって引き出すデータを絞り込んでいる。

app/controllers/plans_controller.rb
class PlansController < ApplicationController
# 色々略

  def index
# 色々略

      plans_nonorder = Plan.includes(:review_items).where(user_id: current_user.id).page(params[:page])

      if params[:status].present?
        if params[:status] == "進行中"
          filterd_plans = plans_nonorder.where(status:"進行中")
        elsif params[:status] == "中止/完了"
          filterd_plans = plans_nonorder.where(status:"中止").or(plans_nonorder.where(status:"完了"))
        else
          filterd_plans = plans_nonorder
        end
      else
        filterd_plans = plans_nonorder
      end
      @plans = filterd_plans.order(deadline: :desc)

# 略
  end

# 略

params[:status] にプルダウンの値が入ってくる。

3. jsファイル修正

Ajax通信が行われると、コントローラーに飛んだ後はindex.js.erbにゆく。

app/views/plans/index.js.erb
var plans = document.querySelector("#plan_list");
plans.innerHTML = '<%= j render 'planlist' %>';

 これはビューファイルのid = plan_list で囲まれた箇所のみを書き換える処理である。

4. 一覧画面に部分テンプレート追加

 ここまでだけだとうまくいかないので、部分テンプレートをつくる。目標一覧画面を修正する。

app/views/plans/index.html.erb
<%# 略 %>

<%= form_with url: plans_path, method: :get, local: false do |f| %>
    <%= f.select :status, ["進行中","中止/完了","全て"] ,{class: "form-control"}%>
    <%= f.submit   "絞り込み" ,{class: "btn-primary"}%>
<% end %>

<div id="plan_list">
    <%= render partial: 'planlist' %>
</div>
<%# 略 %>

 部分テンプレートは頭に_をつけて作成する。

app/views/plans/_planlist.html.erb
<% @plans.each.with_index(1) do |plan, i| %>
    <%= plan.name %>
    <%= plan.status %>
<% end %>

 本当はデザインの関係でdivとかいっぱいあるけど、省略している。

5. ページネーションも追加する

 これだけだとページネーションの処理がうまくいかない。部分テンプレートのところを修正する。

app/views/plans/_planlist.html.erb
<% @plans.each.with_index(1) do |plan, i| %>
    <%= plan.name %>
    <%= plan.status %>
<% end %>
<% if @plans.empty? %>
<%# ページネーション非表示 %>
<% else %>
<nav aria-label="Page navigation example">
  <ul class="pagination">
    <%= paginate @plans, remote: true %>
  </ul>
</nav>
<% end %>

 このremote: trueが重要。これによってページネーションもAjax通信で行われ、部分テンプレートの箇所のみが更新される。

うごく

ly.gif

おわり

 今月はずっとこれをやっていたのでうまくいってよかった。次はいよいよ振り返り機能を見直していくぞ。

2
0
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
2
0