I have the following code that denotes an active tab whenever the user is on a certain subpage, in this case the Users index view.
<li class="<%='active' if current_page?(users_path) %>">
<%= link_to 'Users', users_path %></li>
I'd like it so that the tab is shown as "active" whenever the user is on any of the show, edit, OR index pages.
I tried something like this:
<li class="<%='active' if current_page?(users_path || edit_user_path || user_path) %>">
<%= link_to 'Users', users_path %></li>
But only users_path is recognized.
What's the correct way to build an OR statement into the current_page method?
that should be
<li class="<%='active' if current_page?(users_path) || current_page?(edit_user_path) || current_page?(user_path) %>">
this will be hard to maintain if you're doing this to a lot of pages. You are better of using a gem for semantic navigation.
This is some code I've used in previous apps.
def nav_item(copy, link)
content_tag :li, class: nav_class(link) do
link_to copy, link
end
end
def nav_class(page)
case page
when :users then 'active' if request.path.match(/^\/users/)
when :projects then 'active' if request.path.match(/^\/projects/)
else
nil
end
end
The two helper methods above will render a link inside a li tag with class="active" if the route matches the current path.
Not on a UsersController action:
<%= nav_item('Users', :users) %> #=> <li>Users</li>
On a UsersController action:
<%= nav_item('Users', :users) %> #=> <li class="active">Users</li>
Related
I use current_page? to detect the current page and style that link differently like this :
<li class="snavitem <%= ' active' if current_page? countries_path %>">
Now if we are at /countries then this will add the active class to the link which will make it different. But how to style the link like this when we are in sub pages like countries/new, countries/edit ?
The simple way is smth like this:
current_page?(controller: 'countries')
countries/ #=> true
countries/anything-here #=> true
Define a method check_action in application helper
def check_action controller, action
return true if controller.eql?("countries") and (action.includes?("index") or action.includes?("edit") or action.includes?("new"))
end
In view
<li class="snavitem <%= ' active' if check_action(controller, controller.action_name) %>">
You can use request.fullpath to get current full path
example
<ul>
<% Contry.all.each do |c| %>
<li class="snavitem <%= is_active?(edit_contry_path(c)) %>">
<%= link_to "edit " + c.name, edit_contry_path(c) %>
</li>
<% end %>
</ul>
and on your application_helper.rb
def is_active?(link_path)
"active" if request.fullpath == link_path
end
read about request.fullpath here
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.
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
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 %>
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 %>
I am trying to set an li class of active based on what page the user is on.
I have 4 navigation elements and they all look something like this:
<% if #activeLi == "home" %>
<li class="active">
<% else %>
<li>
<% end %>
<%= link_to :controller => "home" do %>
<span>Home</span>
<% end %>
</li>
and then in each controller I just set #activeLi like this:
def index
#activeLi = "about"
end
I know this is pretty basic stuff, but i'm just wondering if there is an easier way to do this?
Well I know one way you can simplify this and thats by getting rid of the need to use those nasty instance variables.
<li class="<%= controller_name == "home" ? 'active': '' %>">
<%= link_to :controller => "home" do %>
<span>Home</span>
<% end %>
</li>
I have a menu which is a ul
Home | Calendar | Settings
I want to highlight (via a css class) the selected tab in the menu.
Some links (Home and Calendar) also have subselections
Home | *Calendar* | Settings
-------------------------
Add event | Edit event
Ofcourse when edit event is selected, Calendar should still be highlighted.
how can I best approach this using rails and css?
Thanks
The simplest way would be to check which controller is being used. I made up controller names, so of course you would replace 'home', 'calendar', and 'settings' with the correct names.
<ul>
<li class="<%= "highlighted" if params[:controller] == "home" %>">Home</li>
<li class="<%= "highlighted" if params[:controller] == "calendar" %>">Calendar</li>
<li class="<%= "highlighted" if params[:controller] == "settings" %>">Settings</li>
</ul>
In your helper file:
def is_active?(page_name)
"active" if params[:action] == page_name
end
In the template file:
link_to 'Home', '/', :class => is_active?("index")
link_to 'About', '/about', :class => is_active?("about")
link_to 'contact', '/contact', :class => is_active?("contact")
I found this on: http://juliocapote.com/post/52081481/highlight-link-based-on-current-page-in-rails
I settled on this solution which I like a lot:
In the helper
def active_if(options)
if params.merge(options) == params
'nav-active'
end
end
And in the view define what makes the route unique:
<%= link_to 'Home', root_path, class: active_if(action: 'home') %>
<%= link_to 'Aricles', articles_path, class: active_if(controller: 'articles') %>
I have the same problem and end up creating helper.
basicly it replace the link_to url helper so it wrap the link with li and add class "menu_selected" if the current controller matches the link controller
usage sample
<%= menu_link_to "Home", home_path %>
def menu_link_to(*args, &block)
url = args[1]
mapping = ActionController::Routing::Routes.recognize_path(url)
class_property = "menu_selected" if mapping[:controller] == controller.controller_path
content_tag :li, :class => class_property do
link_to *args, &block
end
end
Update to #ahmy's answer for Rails 3.2:
def menu_list_item(*args, &block)
url = args[1]
mapping = Rails.application.routes.recognize_path(url)
li_class = 'active' if mapping[:controller] == controller.controller_path
content_tag :li, :class => li_class do
link_to *args, &block
end
end
i.e. Rails.application.routes.recognize_path instead of ActionController::Routing::Routes.recognize_path.
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
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
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.
Take a look at TabsOnRails
You could just do this:
<%= current_page?(:controller => 'your_controller', :action => 'index') ? 'current' : '' %>
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')}
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.
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
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>