検索可能なプルダウンリストで、二つのフォームを連動させる。
auto_completeの使い方が分かってきたところで、最初の銀行支店をスマートに選択する課題に戻ってみる。
- まず、銀行と支店を検索するので、text_fieldを二つ用意した。
- そうすると、二つのtext_fieldはお互いに連携している必要がある。以下のような連携を求めてみた。
以下のような銀行テーブル、支店テーブルを想定して...
id | name | kana |
---|---|---|
1 | みずほ | ミズホ |
5 | 三菱東京UFJ | ミツビシトウキョウUFJ |
9 | 三井住友 | ミツイスミトモ |
... | ... | ... |
id | code | name | kana | bank_id |
---|---|---|---|---|
1001 | 1 | 本店 | ホンテン | 1 |
1005 | 5 | 丸之内支店 | マルノウチ | 1 |
... | ... | ... | ... | ... |
以上のことを踏まえて、以下のようなコードを考えてみた。
<%# ビュー %> <%= text_field_with_auto_complete :bank, :kana %> <%= hidden_field :payee_account, :bank_id %> <%= text_field_with_auto_complete : branch, :kana %> <%= hidden_field :payee_account, : branch_id %>
# コントローラー:銀行の検索 def auto_complete_for_bank_kana find_options = { :conditions => [ "LOWER(kana) LIKE ?", '%' + params[:bank][:kana].downcase + '%' ], :order => "kana ASC", :limit => 10 } @items = Bank.find(:all, find_options) render :partial => 'auto_complete_for_bank_kana' end # コントローラー:支店の検索 def auto_complete_for_branch_kana Branch.with_scope(:find=>{:conditions=>[ "bank_id=?", params[:payee_account][:bank_id] ]}) do find_options = { :conditions => [ "LOWER(kana) LIKE ?", '%' + params[:branch][:kana].downcase + '%' ], :order => "kana ASC", :limit => 10 } @items = Branch.find(:all, find_options) render :partial => 'auto_complete_for_branch_kana' end end
ここまで書いて、疑問発生!支店を検索する時に、現在選択済みの銀行コードはどうやって取得すれば良いのだろう?
- text_field_with_auto_complete :branch, :kanaと書いた時は、text_fieldに文字列が入力されると、コントローラーのauto_complete_for_branch_kanaが呼び出される。
- コントローラーでは、params[:branch][:kana]で、その時入力された文字列を取得できる。
- きっとtext_field_with_auto_completeのところで、欲しい銀行コードを送信しておく必要があるはず...。
- とりあえずここでは、仮にparams[:payee_account][:bank_id]でその銀行コードを取得できると考えて、書いておいた。
auto_completeで、欲しい情報を追加する
調査と試行錯誤の結果、:withオプションを利用して、以下のように設定すれば、銀行コードも一緒にパラメーターとして送信できるようだ。
<%= text_field_with_auto_complete :branch, :kana, {}, :with=>"value + '&payee_account[bank_id]=' + $('payee_account_bank_id').value" %>
- 「value」は、text_field_with_auto_complete :branch, :kanaに入力された値を送信する。
- 「'&payee_account[bank_id]='」はparams[:payee_account][:bank_id]のキーの部分。
- 先頭の「&」はパラメーターの区切り記号。
- ' 'クォーテーションで囲う必要あり。
- 「$('payee_account_bank_id').value" 」でid属性を指定して、その値を取り出している。
-
-
- どうにか欲しい情報を送信できるようになったが、:withオプションの使い方を正しく理解できていない...。最初のvalueは何故valueだけで大丈夫なんだろうか?
- 参考ページ:How to use text_field_with_auto_complete in Ruby on Rails
-
これで、銀行コードと連携した支店検索が可能になったので、あとは選択リストの表示を制御すれば良い。以下のようにやってみた。
<%# ビュー_auto_complete_for_bank_kana.rhtml %> <ul> <% @items.each do |item| %> <li> <span connect="payee_account_branch_id"></span> <span connect="branch_kana"></span> <span connect="payee_account_bank_id"><%= item.id %></span> <span class="informal"><%= item.kana %></span> <span connect="bank_kana"><%= item.name %></span> </li> <% end %> </ul>
<%# ビュー_auto_complete_for_branch_kana.rhtml %> <ul> <% @items.each do |item| %> <li> <span connect="payee_account_branch_id"><%= item.id %></span> <span class="informal"><%= item.kana %></span> <span connect="branch_kana"><%= item.name %></span> </li> <% end %> <% if params[:payee_account][:bank_id].blank? %> <li> <span connect="payee_account_branch_id"></span> <span connect="branch_kana"></span> <span class="informal">銀行を先に入力してください。</span> </li> <% end %> </ul>
これで、銀行と支店が連動した検索が可能になったが、一つ問題に気付いた。1件も見つからなかった時に何も表示されないので、キー入力に対して反応がないと勘違いしてしまうのだ。以下のように修正した。
<%# ビュー_auto_complete_for_bank_kana.rhtml %> <ul> <% @items.each do |item| %> <li> <span connect="payee_account_branch_id"></span> <span connect="branch_kana"></span> <span connect="payee_account_bank_id"><%= item.id %></span> <span class="informal"><%= item.kana %></span> <span connect="bank_kana"><%= item.name %></span> </li> <% end %> <% if @items.blank? %> <li> <span connect="payee_account_branch_id"></span> <span connect="branch_kana"></span> <span connect="payee_account_bank_id"></span> <span connect="bank_kana"></span> <span class="informal">銀行が見つかりません。</span> </li> <% end %> </ul>
<%# ビュー_auto_complete_for_branch_kana.rhtml %> <ul> <% @items.each do |item| %> <li> <span connect="payee_account_branch_id"><%= item.id %></span> <span class="informal"><%= item.kana %></span> <span connect="branch_kana"><%= item.name %></span> </li> <% end %> <% if params[:payee_account][:bank_id].blank? %> <li> <span connect="payee_account_branch_id"></span> <span connect="branch_kana"></span> <span class="informal">銀行を先に入力してください。</span> </li> <% elsif @items.blank? %> <li> <span connect="payee_account_branch_id"></span> <span connect="branch_kana"></span> <span class="informal">支店が見つかりません。</span> </li> <% end %> </ul>
これで、検索結果が0件であっても、「銀行が見つかりません。」「支店が見つかりません。」と表示されるので安心できる。
検索で一致した部分を強調表示する
ついでに、上記コードの<%= item.kana %>の部分を以下のように変更すれば、一致した部分が強調表示されたリストが得られる。
<%# ビュー_auto_complete_for_bank_kana.rhtml %> ...途中省略... <%= highlight(item.kana, params[:bank][:kana]) %> ...途中省略...
<%# ビュー_auto_complete_for_branch_kana.rhtml %> ...途中省略... <%= highlight(item.kana, params[:branch][:kana]) %> ...途中省略...
ちなみに、auto_complete_result*1のphraseオプション(第3引数)を指定しても、同じように強調表示される。(kanaフィールドだけの表示になってしまうが...。)
render :inline=>"<%= auto_complete_result(@items, :kana, params[:bank][:kana]) %>"
*1:選択リストの内容をhtmlとして返してくれるヘルパメソッド。auto_complete_forによって生成されるメソッドの中で選択リストを描画する時に呼び出されている。(部分テンプレートを利用せずに。)