1

I've got a nav like this:

<nav>
  <ul class='nav nav-pills'>
    <li>
      <%= link_to 'link1', '#' %>
    </li>
    <li>
      <%= link_to 'link1', '#' %>
    </li>
  </ul>
</nav>

My routes, view and controller are set up such that root_url/.../action and root_url/.../action/:page_id will both render the same view, with an instance variable @page being set based on the :page_id param or to a specified default for the action's root. Later in the view, I'm rendering a partial that matches the name of @page.

What I'm trying to do is set class='active' on the <li> whose link text matches the value of @page.

My original inclination was to stay DRY and set window.page_id to match @page and use CoffeeScript to add the class, but that gave me a very noticeable delay between the page loading and the class being set.

Does anyone know the best method of accomplishing this? Right now I'm putting embedded ruby in each one of the <li> elements, which is rather undesirable.

Xavier
  • 3,423
  • 23
  • 36
  • possible duplicate of [Best way to add "current" class to nav in Rails 3](http://stackoverflow.com/questions/3705898/best-way-to-add-current-class-to-nav-in-rails-3) – Yehuda Katz Jan 15 '13 at 05:53

3 Answers3

4

Borrowed and slightly modified to fit your needs from another S.O. post Best way to add "current" class to nav in Rails 3

def nav_link(link_text, page)
  class_name = link_text == page ? 'active' : ''

  content_tag(:li, :class => class_name) do
    link_to link_text, page
  end
end

used like:

nav_link 'Home', @page
Community
  • 1
  • 1
99miles
  • 10,942
  • 18
  • 78
  • 123
  • I think we're on the right track with a helper, but unfortunately this does not work with the root action case without the `params[:page_id]` – Xavier Jan 15 '13 at 03:10
  • Just modify it to your needs. Pass @page then, and compare it to the link text. I modified the answer. – 99miles Jan 15 '13 at 03:14
  • 1
    Submitted my modifications as an answer. Thanks for the help! – Xavier Jan 15 '13 at 03:31
1

Expanding on Zeiv's answer, you can just compare the url:

Helper Method:

def nav_link(link_text, link_path)
  content_tag(:li, class: ('active' if link_path == url_for(only_path: true)) ) do
    link_to link_text, link_path
  end
end

Now in the view you can do this:

<%= nav_link "Some Page", some_page_path %>
justinlyman
  • 148
  • 4
0

Expanding on 99miles's answer, I put this in the corresponding helper:

def nav_link(link_text, link_path, current_page)
  content_tag(:li, class: ('active' if link_text.downcase.gsub(' ', '_') == current_page) ) do
    link_to link_text, link_path
  end
end

That way <li> elements that aren't active don't have an empty class, and it works even when the link text contains spaces.

Used in the view like:

<%= nav_link "My Page", page_path('my_page'), @page %>

Edit:

Or, if you want to specify the text of the link independently from the :page_id

def nav_link(link_text, link_path, page_id, current_page)
  content_tag(:li, class: ('active' if page_id == current_page) ) do
    link_to link_text, link_path
  end
end 

Then you can do

<%= nav_link "My Link", page_path('my_page'), 'my_page', @page %>
Xavier
  • 3,423
  • 23
  • 36