プルダウンリストでキーワードの絞り込み
現状のキーワードを絞り込む操作は、絞り込みたいキーワードのリンクをクリックする。もう一度クリックすると、絞り込み解除。しかしこれだと、現在のページに表示されていないキーワードで絞り込みたい時に困ってしまう。操作環境としては、プルダウンリストが表示されていて、そこから選択したキーワードに絞り込まれる方がいい。
プルダウンリストの取り扱い
プルダウンリストは、編集や新規作成のページで既に利用(app/views/models/softwares/_edit2_keyword.rhtml)しているので、同じ仕組みで簡単に実現できるとやってみが...
collection_select
同じメソッドcollection_selectを利用すると、選択済みのキーワードを、Softwareモデルのkeyword_idとして、インスタンスごと保存しないとうまくいかない...。
# コントローラー @software = Software.new(:keyword_id => 1)
<%# ビュー %> <%= collection_select :software, :keyword_id, Keyword.find_all, :id, :name, :include_blank => true %>
- 単なるIDという数値を扱いたいだけなのに、これだと無駄が多い。
- それにキーワードのリンクをクリックして絞り込む操作も残したいので、工夫しないとうまく連携できない。
select
selectメソッドには、:selectedというオプションがある。以下のようにすれば、Softwareモデルとは無関係に、数値だけを扱うことができそうだ。
# コントローラー @keyword_id = 1
<%# ビュー %> <%= select :software, :keyword_id, Keyword.find_all.collect {|p| [ p.name, p.id ] }, :selected => @keyword_id, :include_blank => true %>
キーワードの絞り込みには、selectメソッドを利用することに決定。
-
-
- collection_selectでも、:selectedや:selected_valueでオプション設定してみたが、指定した値を選択してくれない...。
-
値を監視して、変化したら絞り込む
キーワードのプルダウンリストは表示されるようになったが、キーワードを選択しても、何も起こらない...。それはフォームの送信をしていないからだ。フォームの送信のためには「絞り込み」ボタンを作ればいいのだが、その都度ボタンを押すのは面倒だ。選択したキーワードで自動的に絞り込むようにしたい。Railsが用意してくれたメソッド、observe_fieldを使ってみた。
<%= select :software, :keyword_id, Keyword.find_all.collect {|p| [ p.name, p.id ] }, :selected => @keyword_id.to_i, :include_blank => true %> <%= observe_field :software_keyword_id, :update => "list_update", :submit => "store", :url => {:action => 'list_update'} %>
上記のようにしておくと、:software_keyword_idという場所を監視して、値が変化したら...
- :url=>で指定するメソッドを呼び出す。
- :submit=>で指定するフォームを送信する。
- :update=>で指定する場所を更新する。
-
- すべてhtmlのid属性で指定する。(例:<div id="list_update"><)/span>
- <%= select :software, :keyword_id, ...%>のように指定すると、id属性はsoftware_keyword_idになる。
-
実際のコード
app/views/models/softwares/_list_form.rhtml
- キーワードのプルダウンリストの位置を、キーワード列と合わせたいため、テーブル表示にした。
- プルダウンリストが値を保持するので、キーワードのhidden_fieldは削除した。
- 条件をリセットするリンクは、ページの下に「新規作成 | リセット」のように表示するようにした。
<%# ----ファイル名 app/views/models/softwares/_list_form.rhtml------ %> <div id="store"> <%= form_remote_tag :update => "list_update", :submit => "store", :url => {:action => 'list_update'} %> <table width=100%><tr> <td width=70%> <span style="font-weight:bold;"> <%= human_attribute_name(Software, "title") %>/<%= human_attribute_name(Software, "description") %> </span>を検索 : <%= text_field_tag("store_search_word", @search_word) %> <%= submit_to_remote "store", "検索", :update => "list_update", :submit => "store", :url => {:action => 'list_update'} %> <small> <%= link_to_remote "クリア", :update => "list_update", :submit => "store", :url => {:action => 'list_update', :store_search_word => ""} %> </small> </td> <td width=16%> <%= select :software, :keyword_id, Keyword.find_all.collect {|p| [ p.name, p.id ] }, :selected => @keyword_id.to_i, :include_blank => true %> <%= observe_field :software_keyword_id, :update => "list_update", :submit => "store", :url => {:action => 'list_update'} %> <%= hidden_field_tag("store_order_field", @order_field) %> <%= hidden_field_tag("store_order_direction", @order_direction) %> <%#= hidden_field_tag("store_keyword", @keyword_id) %><%# <---削除、selectに置き換えた %> </td> <td> </td> </tr></table> <%= end_form_tag %> </div>
app/controllers/softwares_controller.rb
- プルダウンリストからのパラメーターを受け取るために、params[:software] && params[:software][:keyword_id]のように取得した。params[:software][:keyword_id]だけでは、listアクションで、nil[:keyword_id]のハッシュ値を求めてエラーになってしまった。
- paramsで取得する値は、文字列になってしまうようだ。@keyword_idはselectメソッドで利用するとき、selected=>@keyword_id.to_iのように変換する必要がある。
# ----ファイル名:app/controllers/softwares_controller.rb------ ...(途中省略)... def set_pagination #パラメーターを取得 ###以下変更 #@keyword_id = params[:keyword] || params[:store_keyword] || "%" @keyword_id = params[:keyword] || (params[:software] && params[:software][:keyword_id]) || "%" @order_field = params[:order_field] || params[:store_order_field] || "id" @order_direction = params[:order_direction] || params[:store_order_direction] || "ASC" @search_word = params[:store_search_word] #条件によって、パラメーターを変更 ###以下変更 #@keyword_id = "%" if params[:keyword] == params[:store_keyword] @keyword_id = "%" if params[:keyword] == (params[:software] && params[:software][:keyword_id]) ###1行追加 @keyword_id = "%" if @keyword_id.to_i < 1 @order_direction = 'ASC' if params[:order_field] && !(params[:order_field] == params[:store_order_field]) @direction_mark = @order_direction == 'DESC' ? '▼' : '▲' @order_next_direction = @order_direction == 'DESC' ? 'ASC' : 'DESC' #paginate処理 conditions = ["keyword_id LIKE ? AND (title LIKE ? OR description LIKE ?)", @keyword_id ,"%#{@search_word}%" ,"%#{@search_word}%" ] order = "#{@order_field} #{@order_direction}" @software_pages, @softwares = paginate :softwares, :per_page => 2, :conditions => conditions, :order => order end def list_update Software.with_scope(login_user) do @ajax_update = true set_pagination render :action => "list", :layout => false end end ...(途中省略)...
これで、プルダウンリストでキーワードを選択しただけで、絞り込んでくれる。今までのキーワードのリンクをクリックする操作もそのまま使える。現在の見た目はこんな感じ...。