複数のフィルターでさらに絞り込みたい!その3

前回までに、マルチフィルターの基本部分がひとまず完成した。今回は、フィルターの使い勝ってを向上する機能を追加してみた。全ての機能を追加したフィルターの見た目はこんな感じだ。

  • 最初の表示はフィルターなしで、こんな感じ。

  • フィルター条件は自由に追加、削除できる。


それでは早速、作業開始。

行ごとに削除リンクを作る。

今まで、フィルター条件の追加しか出来なかったので、削除のリンクも作ってみた。これはシンプルな方法で実現できた。

  • まず、フィルター条件の1行ごとにid属性を設定しておく。
  • 削除リンクはlink_to_functionで作成する。その中で、Element.remove('削除したいid属性')とするだけでOK。ビューだけの処理で削除が完了してしまった。
app/views/csvs/_list_filter_condition.rhtml
ビュー(フィルター条件の行)
<li id=<%= "filter_remove#{@filter_count}" %>>
<small>
<%= link_to_function '削除', "Element.remove('filter_remove#{@filter_count}')" %>
</small>
...(途中省略)...
</li>

条件の組み合せにAND、ORの選択を可能にする。

今までは、条件を絞り込むフィルターだけであった。時には、条件を広げるフィルターも使いたくなるだろう。これもちょっとした修正で実現可能だ。

  • 「上記すべての条件と一致する」となっていたところをselect_tagで選択可能にした。
  • SQLを接続する演算子は、params[:filter_and_or_op]で取得できるようにした。
app/views/csvs/_list_filter.rhtml
ビュー(フィルターの描画)
...(途中省略)...
<!--フィルターの実行/解除/削除の行-->
<ul>
<small>
上記
<%= select_tag :filter_and_or_op, 
      options_for_select([['すべての', 'AND'], ['いずれかの', 'OR']], 
                         params[:filter_and_or_op]) %>
条件と一致する
<%= submit_to_remote 'csv_filter', 'フィルターを実行', 
                     :update => 'list_update',
                     :submit => 'list_params', 
                     :url => {:action => 'list_update'} %>
...(途中省略)...
</small>
</ul>
app/controllers/csvs_controller.rb
コントローラー
  • sqls.join(params[:filter_and_or_op])とすればOK。これで上記ビューで選択した演算子によって、SQLが接続される。
...(途中省略)...
  def set_pagination
    # :conditionsの設定
    filter = params[:filter] || {"0"=>{:column=>@column_titles[0], :item=>"", :id=>20}}
    sqls = []
    filter.each {|c, f| sqls << Filtersql.human_compair_sql(f[:column], f[:item], f[:id])}
    @conditions = sqls.join(params[:filter_and_or_op])
...(途中省略)...

フィルターを一時的に解除する。

もしかしたら便利かもしれないと思い、クリックするとフィルター条件はそのままに、一時的にフィルターを解除するリンクも作ってみた。

app/views/csvs/_list_filter.rhtml
ビュー(フィルターの描画)
  • パラメーターを送信する範囲に、フィルター条件を含めないようにした。それ以外は「フィルターを実行」と同じだ。
...(途中省略)...
<%= link_to_remote 'フィルターを一時的に解除', 
                   :update => 'list_update',
                   :submit => 'no_filter_params', 
                   :url => {:action => 'list_update'} %>
...(途中省略)...
app/views/csvs/list.rhtml
ビュー(リスト表示全体の描画)
  • id="no_filter_params"は、並べ替え条件を維持するパラメーターの範囲に設定した。
<% if controller.action_name == 'list' %>
  <h1>CSVリスト</h1>
  
  <div id="list_params">
  <%= render :partial => 'list_filter' %>
  <div id="list_update">
<% end %>
<!----以上listアクションの時だけ描画----list_updateはこれ以下を描画する------------------>

<div id="no_filter_params">
  <%# [フィルタを解除]をクリックすると、id="no_filter_params"の範囲だけ送信される。 %>
  <%# 並び替え条件を維持するため。 %>
  <%= hidden_field_tag(:sort_field, params[:sort_field]) || 'id' %>
  <%= hidden_field_tag(:sort_direction, params[:sort_direction]) %>
</div>
...(途中省略)...

全てのフィルター条件を削除する。

フィルター条件がたくさんある時、1行ごとに削除するのは面倒なので、フィルター条件を全て削除するリンクも作成した。

  • 更新する部分は、レイアウトも含めたページ全体。
  • パラメーターは並べ替え条件を維持する範囲だけ送信。
  • delete_all_filterアクションを新規作成して、その中でlistアクションへリダイレクトする。
app/views/csvs/_list_filter.rhtml
ビュー(フィルターの描画)
<%= link_to_remote '全てのフィルター条件を削除', 
                   :update => 'layout_update',
                   :submit => 'no_filter_params', 
                   :url => {:action => 'delete_all_filter'} %>
app/views/layouts/csvs.rhtml
ビュー(レイアウトファイル)
  • 以下のようにレイアウトファイル全体にid="layout_update"属性を設定した。これで、ajax更新なんだけど、listアクションの結果がそのまま描画されると思う。
  • もしかしたら、上記リンクをクリックするごとに、divダグがネスト(入れ子、<div><div>...のような状態)されていくかもしれない...。(でも、追加と削除を10回くらい繰り返して問題なかったのでこのままにした。)
<div id="layout_update">
...(途中省略)...
</div>
app/controllers/csvs_controller.rb
コントローラー
  • 並び替え維持のパラメーターと共にリストアクションへリダイレクトしているだけ。
...(途中省略)...
  def delete_all_filter
    redirect_to :action => 'list', :sort_field => params[:sort_field], :sort_direction => params[:sort_direction]
  end
...(途中省略)...


以上で、マルチフィルターはひとまず完成だ!