1

I have a navigation bar which is an unordered list with tabs as list elements. I'm drawing each individual tab (list item) using a view helper. I want to apply the active class on each one based on a value provided by a view. Is this possible?

To elaborate, on the view helper I might have something like:

def tab_item(tab)
  content_tag :li, :class => ('active' if some_variable == tab) do
    link_to tab, "/#{tab}"
  end
end

And in a specific view I would do:

<% somehow_set_some_variable('dash') %>

This would then make it so that some_variable in the view helper is 'dash', making it so that that tab gains the 'active' class.

Is this possible in any way? If not, is there another approach to this problem? Should I just set a variable on the controller?

I have seen articles and questions already which base the decision based on the current controller and/or action, but this is too restrictive so I am looking to see if I can take this approach. Another solution I came up with is to generate the entire list of tabs in one view helper which takes an argument for the tab to be activated, and I call this in each of the views. However, I'd rather generate the list in the layouts and activate a tab on a per-view basis.

Workaround: So far I have come up with a compromise, short of knowing a way of doing what I asked in this question. The application helper creates an li tag and applies activate if the passed in argument to the application helper matches instance variable @activate.

def nav_tab(tab)
  content_tag :li, :id => tab, :class => ('active' if tab == @activate) do
    link_to tab, "/#{tab}"
  end
end

Then in controller actions I simply set that variable, for example:

def index
  # ...
  @activate = 'dash'
end

This works, and it has the effect I was looking for: the nav bar is generated independently and then each 'action' can specify which tab to activate, if they want.

I am not sure if this is the best solution to this problem. I was trying to keep this stuff within views, like this question which accomplishes this for view-specific <title> changes.

Community
  • 1
  • 1
Jorge Israel Peña
  • 36,800
  • 16
  • 93
  • 123

1 Answers1

0

You could try this just define a methods in application helper and call it by passing the a unique string for each navigation list

 def active_class(css_class)

    if controller.controller_name == css_class ||  css_class == "#{controller.controller_name}##{controller.action_name}" || css_class == inner_classes
       return "active"
    else
      return ""
    end   
  end


  def inner_classes
    pages = {
      "basic_files#new_part_price_file" => "basic_files#index",
      "basic_files#new_market_basket_file" => "basic_files#index",
      "basic_files#create" => "basic_files#index",
      "basic_files#edit"   => "basic_files#index",
      "basic_files#show"   => "basic_files#index",
      "basic_files#uploads"  => "basic_files#index",
      "basic_files#downloadable_part_price_file" => "basic_files#download_page",
      "basic_files#downloadable_market_basket_file" => "basic_files#download_page",
      "basic_files#download_part_price_file" => "basic_files#download_page",
      "basic_files#download_market_basket_file" => "basic_files#download_page",
    }   
    pages["#{controller.controller_name}##{controller.action_name}"]
  end

In the view you could call the above methods like this

<%= link_to 'Home',home_path,:class => "f1 #{active_class('home')}" %>

   <% if current_user.publisher? %>
    <%= link_to 'User',users_path,:class => "f1 #{active_class('users')}" %> 
    <%= link_to 'Upload',basic_files_path,:class => "f1 #{active_class('basic_files#index')}" %>
    <%= link_to 'Publish',publish_completed_basic_files_path,:class => "f1 #{active_class('basic_files#publish_completed')}" %>
    <%= link_to 'Report',audits_path ,:class => "f1 #{active_class('audits')}" %> 

Note it just a example of how you can build automatic navigation highlighting

Viren
  • 5,812
  • 6
  • 45
  • 98