#概要
- Bootstrap3 tabsを使用。
- どのコントローラから呼ばれたかを検知し、activeタブを切り替える。
#経緯
ユーザーがフォームを提出後、検証に引っかかり、エラーメッセージとともにやり直しさせることは、よくあります。全てが別々のテンプレートであれば何も問題がないのですが、タブを使用し一画面で複数の機能を持たせる場合、activeタブを状況に応じて、切り替えたくなります。
例えば、タブのひとつに新規作成フォームがあるとします。再レンダリング後は、フォームをactiveにするのが自然です。しかしながら、何もしないと、いつもデフォルトがactiveになってしまいフォームが隠れてしまいます。
#やりたいことの流れ
####1. デフォルトでは表が表示される。
####2. 新規作成用タブをクリックするとフォームが表示される。(検証に引っかかるよう、わざと空フォームを提出)
####3. やり直しさせるのだから、再レンダリング後、(デフォルトのページを表示する代わりに)フォームのタブをactiveにしたい。
#解決策
解決策のひとつとして現在のコントローラ名に応じて、タブを切り替える方法があります。テンプレートはHAMLで書いています。
以下の例では、デフォルト:#tabs_1がactiveで、MovingItemsControllerからレンダリングされた場合のみ例外的に#tabs_2をactiveにするとします。
####1. 最初、レンダリング前にCSSクラスを入れ替える方法を考えました。
show.html.haml
-# タブ用クラス
- active_tab = "active"
- active_content = %w[tab-pane fade active in]
- default_tab = ""
- default_content = %w[tab-pane fade]
-# タブ交換機 in Ruby
- if params[:controller] == 'moving_items'
- tab1, content1 = default_tab, default_content
- tab2, content2 = active_tab, active_content #<= ACTIVE
- else
- tab1, content1 = active_tab, active_content #<= ACTIVE
- tab2, content2 = default_tab, default_content
/ タブ
%ul{ class: "nav nav-tabs", role: 'tablist' }
%li{ class: tab1 }
%a{ href: "#tabs_1", role: "tab", data: { toggle: "tab" } }
All items
%li{ class: tab2 }
%a{ href: "#tabs_2", role: "tab", data: { toggle: "tab" } }
Add item
/ タブコンテンツ
.tab-content
#tabs_1{ class: content1 }
- if @moving_items.count > 0
= render 'moving_items/table'
- else
%p No item found
#tabs_2{ class: content2 }
= render 'moving_items/form'
####2. その後、リファクタリングしていたら、JavaScriptで対応した方がスッキリすることに気がつきました。
show.html.haml
/ タブ
%ul{ class: "nav nav-tabs", role: 'tablist', id: "tabs_movings" }
%li{ class: "active" }
%a{ href: "#tabs_1", role: "tab", data: { toggle: "tab" } }
All items
%li
%a{ href: "#tabs_2", role: "tab", data: { toggle: "tab" } }
Add item
/ タブコンテンツ
.tab-content
#tabs_1{ class: "tab-pane fade active in" }
- if @moving_items.count > 0
= render 'moving_items/table'
- else
%p No item found
#tabs_2{ class: "tab-pane fade" }
= render 'moving_items/form'
:coffee
// タブ交換機 in JavaScript
// ページが読み込まれた後、2番目のタブをactiveにする。
jQuery ->
if #{ params[:controller] == 'moving_items' }
$('#tabs_movings li:eq(1) a').tab('show')
以上です。