Ruby on rails and tabs
Solution 1
If you want something more flexible, checkout the tabs_on_rails plugin I created to solve exactly this common pattern.
In your template use the tabs_tag
helper to create your tab.
<% tabs_tag do |tab| %>
<%= tab.home 'Homepage', root_path %>
<%= tab.dashboard 'Dashboard', dashboard_path %>
<%= tab.account 'Account', account_path %>
<% end %>
The example above produces the following HTML output.
<ul>
<li><a href="/">Homepage</a></li>
<li><a href="/dashboard">Dashboard</a></li>
<li><a href="/account">Account</a></li>
</ul>
The usage is similar to the Rails route file. You create named tabs with the syntax tab.name_of_tab
.
The name you use creating a tab is the same you’re going to refer to in your controller when you want to mark a tab as the current tab.
class DashboardController < ApplicationController
set_tab :dashboard
end
Now, if the action belongs to DashboardController
, the template will automatically render the following HTML code.
<ul>
<li><a href="/">Homepage</a></li>
<li class="custom"><span>Dashboard</span></li>
<li><a href="/account">Account</a></li>
</ul>
Solution 2
Create a helper to build that menu for you:
def menu_builder(page_id)
tabs = ['home','store','faq']
content = ""
tabs.each do |tab|
content << if page_id == tab
content_tag('li', content_tag('a', tab, :href => nil ), :class => 'current') + " "
else
content_tag('li', content_tag('a', tab, :href => "/#{tab}" )) + " "
end
end
content
end
Or my own short version of it:
def menu_builder(page_id)
["home", "store", "faq"].map { |tab|
%{<li class="#{page_id == tab ? "active" : "inactive"}"><a href="#{tab}">#{tab.capitalize}</a></li>}
}.join("\n")
end
page_id
is an identifier of some page and should be defined in your controllers.
class Foo < ApplicationController
def faq
@page_id = 'faq'
...
end
end
Then just use it in the template:
<ul>
<%= menu_builder(@page_id) %>
<li class="search">...</li>
</ul>
Solution 3
Take a look an this plugin:
http://github.com/paolodona/rails-widgets
It has lots of cool components including navigation.
Documentation: https://github.com/paolodona/rails-widgets/wiki
Solution 4
I created tabulous to solve this problem. There is a separate tab configuration file where you can describe how you want your tabs to behave. For example:
Tabulous.setup do
tabs do
pictures_tab do
text { 'Pictures' }
link_path { pictures_path }
visible_when { true }
enabled_when { true }
active_when { in_action('any').of_controller('pictures') }
end
music_tab do
text { 'Music' }
link_path { songs_path }
visible_when { true }
enabled_when { current_user.has_music? }
active_when { in_action('any').of_controller('songs') }
end
profile_tab do
text { 'My Profile' }
link_path { account_path(current_user) }
visible_when { true }
enabled_when { true }
active_when { in_actions('show', 'edit', 'update').of_controller('accounts') }
end
end
end
Read the tabulous documentation to learn more.
Related videos on Youtube
Comments
-
Johan almost 2 years
I'm still a beginner with ruby and rails, and now I'm googling about methods for creating a tabbed menu, marking the list element of the currently active controller with a css class "current". There are many hits on google, but I haven't found any that I manage to get working.
I have my menu here:
<ul> <li class="current"><%= link_to 'Home', root_path %> </li> <li><%= link_to 'Browse songs', page_path('browse') %> </li> <li><%= link_to 'Add song', new_song_path %> </li> <li><%= link_to 'Request song', artists_path %> </li> <li><%= link_to 'My ReChord', artists_path %> </li> <li><%= link_to 'Help', page_path('help') %> </li> <li id="search"><form><input type="search" placeholder="Type here to find a song or an artist"/></form> </li> <li class="notab"> <% if user_signed_in? %> <%= link_to 'Sign out', destroy_user_session_path %> <% else %> <%= link_to 'Sign in', new_user_session_path %> or <%= link_to 'sign up', new_user_registration_path %> <% end %> </li> </ul>
Now I have class="current" hard coded on the Home tab. However, when clicking for example Browse songs, I want the class="current" to be moved to the corresponding list element for that line.
Note that I have some links that just is the route path (like new_song_path) and some links that are sub pages, like page_path('help'). I need it to work for both these types of links.
Can you provide me with either a good tutorial suitable for my two days long experience with rails, or (preferably) example code that might fit perfectly on my list above? Thanks in advance!
-
Jonathan over 13 yearsBig fan of the widgets' tabnav -- have used it on many projects
-
Johan over 13 yearsThanks! But how can I make it work with page_path('browse') and page_path('help'), which are to be two different tabs?
-
Johan over 13 yearsI mean, I have one controller called page. In the controller, I have a function called show. In that function, I do render :partial => params[:id]. I would need to run set_tab with a dynamic parmeter in some way. I'm completely new to rails.
-
Simone Carletti over 13 yearsYou can call set_tab in your action or use a before_filter.
-
Johan over 13 yearsOkay, but I mean, how can I use set_tab with a dynamic value? I mean, I have only one action with a render :partial => params[:id]. I want like set_tab params[:id], but that does not seem to work.
-
Simone Carletti over 13 yearsYes, you can do this. But the in your template you need to configure a tab.<ID_NAME> for each possible ID. Did you read the documentation?
-
Teemu Leisti almost 11 yearsI'd like to add a recommendation for Tabulous. I've been using it for a while now, and it's a very good gem.
-
broschb over 9 yearsI had to add .html_safe to the return from menu_builder(page_id) method to get this to work