How do I apply an 'active' class to my navigation based on the current_page in a DRY way? - Rails 3
So in my application.html.erb
I have my navigational structure that looks something like this:
<div id="navigation">
<ul class="pills">
<% if current_page?(:controller => 'welcome', :action => 'index') %>
<li><%= link_to "Profile", vanity_path(:vname =&g开发者_如何转开发t; current_user.username) %></li>
<li><%= link_to "Settings", settings_path %></li>
<li><%= link_to "Sign Out", signout_path %></li>
<% elsif !current_page?(:controller => 'welcome', :action => 'index') %>
<li><%= link_to "Home", root_path %></li>
<li><%= link_to "Profile", vanity_path(:vname => current_user.username) %></li>
<li><%= link_to "Settings", settings_path %></li>
<li><%= link_to "Sign Out", signout_path %></li>
<% end %>
</ul>
</div>
However, what I would like to do, is once they are on any of the pages in the navigation, it applies a class active
to the respective link.
So for instance, if the user is on mydomain.com/johnbrown
which is the Profile
link, the rails helper would look something like this:
link_to "Profile", vanity_path(:vname => current_user.username), :class => "active"
.
But how do I do that in a programmatic way, so I am not duplicating content? i.e. how do I get that functionality for all the pages in my navigation and write it as DRY as possible?
Thanks.
This is a really great question. I've never really been happy with the solutions I've seen or come up with. Maybe we can get one together here.
Here is what I've tried in the past
I've made a helper that returns a hash with :class defined since I use HAML
def active_tab(path)
request.path.match(/^#{path}/) ? { :class => 'active' } : {}
end
ex usage:
= link_to "Dashboard", dashboard_path, active_tab("#{dashboard_path}$")
Or an alternative along the same lines
def active_class(path)
request.path =~ /#{path}/ ? 'active' : nil
end
ex usage:
= link_to 'Presentations', admin_presentations_path, :class => "#{active_class('presentations')}"
I would love to see some other suggestions on this.
I found this answer for a bootstrap related navbar but you could easily use it with your nav.
Answer taken from here
You can use helper for handle "current_page?", example a method :
module ApplicationHelper
def is_active?(link_path)
if current_page?(link_path)
"active"
else
""
end
end
end
example bootstrap navbar
<div class="navbar">
<div class="navbar-inner">
<a class="brand" href="#">Title</a>
<ul class="nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
</ul>
</div>
</div>
So, on view looks like
<li class="<%= is_active?(some_path) %>">
<%= link_to "name path", some_path %>
</li>
For Haml
Just simple looks like :
%ul.nav
%li{class: current_page?(some_path) && 'active'}
= link_to "About Us", some_path
You may define a helper method in application_helper.rb
def create_link(text, path)
class_name = current_page?(path) ? 'my_class' : ''
content_tag(:li, class: class_name) do
link_to text, path
end
end
Now you can use like:
create_link 'xyz', any_path
which would render as
<li class="my_class">
<a href="/any">xyz</a>
</li>
Hope it helps!
Why don't you just take the redundant parts out of the if else block? Also take a look at 'link_to_unless'
<div id="navigation">
<ul class="pills">
<li><%= link_to_unless(current_page?(:controller => 'welcome', :action => 'index'), "Home", root_path %></li>
<li><%= link_to "Profile", vanity_path(:vname => current_user.username) %></li>
<li><%= link_to "Settings", settings_path %></li>
<li><%= link_to "Sign Out", signout_path %></li>
</ul>
</div>
then I would add some jQuery to inject active class into the link that matches the window.location pattern.
精彩评论