Dave
Dave

Reputation:

Changing Current Tab in Rails

I have a list of tabs at the top of my application that I include in a general layout in application.html.erb. They look like this:

<li class="current"><%= link_to "Home", provider_path(current_user.id), :method=> "GET"%> </li>
            <li><%= link_to "Edit Profile", edit_student_path(current_user.id) %> </li>
            <li><%= link_to "Search", provider_search_path %> </li>

I want to change the selected tab to the "current" one, when I hit that page. So when I click Edit Profile and the Edit Profile page loads, the tabs should appear as follows:

<li><%= link_to "Home", provider_path(current_user.id), :method=> "GET"%> </li>
 <li class="current"><%= link_to "Edit Profile", edit_student_path(current_user.id) %> </li>
  <li><%= link_to "Search", provider_search_path %> </li>

Is there a way to do this outside of adding javascript to the page which is displayed? Or if there is what is generally best practice for doing this in the DRYest way possible.

Thanks

Upvotes: 10

Views: 5235

Answers (8)

Martin Graham
Martin Graham

Reputation: 116

I did this in the application helper and it seems to work fine:

def current_page(path)
  "active" if current_page?(path)
end

Then call like this:

<li class="<%= current_page(root_path)%>"> <%= link_to "Home", root_path %></li>

Upvotes: 0

Noz
Noz

Reputation: 6346

I made a helper for this that can accept any number of arguments which is useful for nested resources, but it also accepts a single controller name just like the other answers.

application-helper.rb:

 def is_active(*links)  
   links.each { |link| return "active" if params[:controller] == link }
 end

application.html.erb:

<li class="<%=is_active('home')%>">...</li>

Or

Example usage with HAML & nested resource(will be active for any of the provided controller names):

applcation.html.haml:

%li{:class => is_active('blogs', 'comments')}

Upvotes: 1

Guido
Guido

Reputation: 47665

Take a look at TabsOnRails

Upvotes: 3

Adam Dorsey
Adam Dorsey

Reputation: 21

You could just do this:

<%= current_page?(:controller => 'your_controller', :action => 'index') ? 'current' : '' %>

Upvotes: 2

danivovich
danivovich

Reputation: 4217

You can use controller.class == and controller.action_name == to figure out exactly which controller and action you are on

so it would be something like

<li class="<%= controller.class == ProviderController and controller.action_name == 'show' ? 'current' : '' %>"><%= link_to "Home", provider_path(current_user.id), :method=> "GET"%> </li>
<li class="<%= controller.class == StudentController and controller.action_name == 'edit' ? 'current' : '' %>"><%= link_to "Edit Profile", edit_student_path(current_user.id) %> </li>
<li class="<%= controller.class == ProviderController and controller.action_name == 'search' ? 'current' : '' %>"><%= link_to "Search", provider_search_path %> </li>

I believe there are some ways to get the current url for the page you are on, but then your "active" styling will be dependent on only getting to that action via that path, which may not always be the case depending on the routes, this way will ensure the view shows what is true based on what was actually run, not what the url is in the address bar

Upvotes: 11

kafuchau
kafuchau

Reputation: 5593

You could try something like:

<li class="<%= controller.controller_path == 'provider' ? 'current' : '' %>"><%= link_to "Home", provider_path(current_user.id), :method=> "GET"%> </li>
<li class="<%= controller.controller_path == 'student' ? 'current' : '' %>"><%= link_to "Edit Profile", edit_student_path(current_user.id) %> </li>
<li class="<%= controller.controller_path == 'search' ? 'current' : '' %>"><%= link_to "Search", provider_search_path %> </li>

...and just check which controller you're coming from.

Upvotes: 6

Andy Gaskell
Andy Gaskell

Reputation: 31761

I'm so not claiming this is the best way to do this, however I am brave enough to post what I came up with :)

Some example menu links from my layout:

<li class="nav-calendar"><%= menu_link_to 'teachers', 'show_date', 'Calendar', calendar_url  %></li>
<li class="nav-announcements"><%= menu_link_to 'announcements', nil, 'Announcements', announcements_path %></li>

Then I created this helper:

def menu_link_to(*args, &block)
  controller = args.shift
  action = args.shift

  if controller == controller_name && (action.nil? || action == action_name)
    if args.third.nil?
      args.push({:class => 'selected'})
    else
      args.third.merge!({:class => 'selected'})
    end
  end

  link_to *args, &block
end

Upvotes: 0

rwilliams
rwilliams

Reputation: 21497

When you switch pages you could pass something like @current_tab back to the erb from the controller methods. Then use @current_tab to decide which li should be the current class. Alternatively, you could give each li and id or some unique attribute and simply change the class with your JavaScript framework of choice.

Upvotes: 0

Related Questions