layam edited this page Apr 1, 2011 · 18 revisions

The Tabnav widgets generates tabbed navigations. It can create horizontal, vertical, nested tabbed navigations.. and you can style it the way you want using CSS hooks.
It provides an easy way to pass highlighting rules and disable tabs at runtime as well.

How to generate a Tabnav

Let’s generate a main tabbed navigation for our site (I’ll call it main, you can call it what you want)

$ script/generate tabnav main
      create  app/views/widgets
      create  app/views/widgets/_main_tabnav.rhtml

It creates a partial with the tabnav definition.
Now we can insert the tabnav wherever we want, I’ll put it in my app/views/layouts/application.html.erb.

  <% tabnav :main do %>					
    ....your contents goes here, like: 
    <%= yield %>	
  <% end %>

Now reload your pages, you should see a Tabbed navigation and one tab for each controller. Now you can edit the app/views/widgets/_main_tabnav.html.erb partial.

Add tabs to the tab file

edit: app/view/widgets/_main_tabnav.html.erb

add_tab do |t|
    t.named "name of tab"
    t.links_to :controller => "orders" # could also be :controller => "orders", :action => "show"

Create custom css

The tabnav generates and inline its own CSS by default. I you want to customize it, you should:

  1. copy the generated CSS you find in the page containing the tabnav (in your browser right click/show HTML)
  2. paste it into your stylesheet file
  3. turn off the automatic CSS generation (see below)

edit: app/view/widgets/_main_tabnav.html.erb

change: render_tabnav :main, :generate_css => true do

into: render_tabnav :main, :generate_css => false do


Sometimes you do not have one tab per controller and want a tab to be highlighted on different conditions.

edit: app/view/widgets/_main_tabnav.html.erb

add: t.highlights_on :controller => "locations" to the relevant tab.

It is not mandatory to highlight by :controller or :action. The highlight_on method will match any request parameter, so that:

add_tab do |t|
    t.named "Animals"
    t.links_to :controller => "animals"
    t.highlights_on :is_animal => "true"

Will highlight on:

  • localhost:3000/animals _matches :controller => “animals” _
  • localhost:3000/animals/index _matches :controller => “animals” _
  • localhost:3000/dogs?is_animal=true matches :is_animal => true
  • localhost:3000/search?name=corky&is_animal=true matches :is_animal => true

note: multiple t.highlights_on statements can be used within a single tab for more granular highlighting logic. eg:

add_tab do |t|
    t.named "Animals"
    t.links_to :controller => "organisms"
    t.highlights_on :controller => "organisms", :action => "mammals"
    t.highlights_on :controller => "organisms", :action => "reptiles"

RESTful tabs links

edit: app/view/widgets/_main_tabnav.html.erb

change: t.links_to :controller => "orders"
to: t.links_to hash_for_orders_path

Conditional tabs

Example: You only want to show a tab if a user is logged in:

add_tab do |t|
  t.named 'Software'
  t.links_to :controller => "programs"
end if logged_in?	

Nested tabs

Create a new tabnav with a different name:

$ ruby script/generate tabnav invoices

Insert the following code in your relevant view file(s):

<%= tabnav :invoices %>

Example: You want a tab for every CRUD action:
edit: app/view/widgets/_invoices_tabnav.html.erb

add_tab do |t|
  t.named "show"
  t.links_to :controller => "invoices", :action => "show"
add_tab do |t|
  t.named "new"
  t.links_to :controller => "invoices", :action => "new"
add_tab do |t|
  t.named "edit"
  t.links_to :controller => "invoices", :action => "edit"

Note: remember to add highlighting rules to the main tabnav, to maintain highlighting.