可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have some static pages in a navigation menu. I want to add a class like "current" to the item which is currently displaying.
The way I am doing so is to add tons of helper methods (each for one item) to check the controller and action.
def current_root_class
'class="current"' if controller_name == "homepage" && action_name == "index"
end
<ul>
<li <%= current_root_class %>><%= link_to "Home", root_path %>
Is there any better way to do so!? My current way is so stupid......
回答1:
Not truly an answer here, because I'm using quite the same way as you are. I've just defined helper methods to test for multiple controller or actions:
In application_helper.rb
def controller?(*controller)
controller.include?(params[:controller])
end
def action?(*action)
action.include?(params[:action])
end
Then you can use if controller?("homepage") && action?("index", "show")
in your views or other helper methods…
回答2:
I made a helper called nav_link
:
def nav_link(link_text, link_path)
class_name = current_page?(link_path) ? 'current' : ''
content_tag(:li, :class => class_name) do
link_to link_text, link_path
end
end
used like:
nav_link 'Home', root_path
which will produce HTML like
<li class="current"><a href="/">Home</a></li>
回答3:
Use the current_page?
helper to determine whether or not you should assign the "current"
class. For example:
<%= 'active' if current_page?(home_about_path) %>
Note you can also pass a path (not only a hash of options), e.g: current_page?(root_path)
.
回答4:
I use this nav_link(text, link) function in application_helper.rb (Rails 3) to get the job done and it rolls my bootstrap twitter 2.0 nav bar links for me.
def nav_link(text, link)
recognized = Rails.application.routes.recognize_path(link)
if recognized[:controller] == params[:controller] && recognized[:action] == params[:action]
content_tag(:li, :class => "active") do
link_to( text, link)
end
else
content_tag(:li) do
link_to( text, link)
end
end
end
Example:
<%=nav_link("About Us", about_path) %>
回答5:
The way I've done it is to add a helper function in the application_helper
def current_class?(test_path)
return 'current' if request.request_uri == test_path
''
end
Then in the nav,
<%= link_to 'Home', root_path, :class => current_class?(root_path) %>
This tests the link path against the current page uri and returns either your current class or an empty string.
I've not tested this thoroughly and I'm very new to RoR (moving over after a decade with PHP) so if this has a major flaw I'd love to hear it.
At least this way you only need 1 helper function and a simple call in each link.
回答6:
To build off @Skilldrick 's answer...
If you add this code to application.js it will make sure that any dropdown menus with active children will also be marked as active...
$('.active').closest('li.dropdown').addClass('active');
To recap supportive code > Add a helper called nav_link:
def nav_link_to(link_text, link_path)
class_name = current_page?(link_path) ? 'active' : ''
content_tag(:li, :class => class_name) do
link_to link_text, link_path
end
end
used like:
nav_link_to 'Home', root_path
which will produce HTML like
<li class="active"><a href="/">Home</a></li>
回答7:
I think the best way is
application_helper.rb:
def is_active(controller, action)
params[:action] == action && params[:controller] == controller ? "active" : nil
end
And in menu:
<li class="<%= is_active('controller', 'action') %>">
回答8:
I know it is a out dated answer, but you can easily ignore all these current page check by using a link_to helper wrapper, called active_link_to gem, it works exactly what you want, add a active class to current page link
回答9:
Here is the full example, on how to add an active class on bootstrap menu page in rails view.
<li class="<%= 'active' if current_page?(root_path) %>"><%= link_to 'Home', controller: "welcome" %></li>
<li class="<%= 'active' if current_page?(about_path) %>"><%= link_to 'About us', about_path %></li>
<li class="<%= 'active' if current_page?(contact_path) %>"><%= link_to 'Contact us', contact_path %></li>
回答10:
I use an awesome gem called Tabs on Rails.
回答11:
For me personally i used a combination of answers here
<li class="<%= 'active' if current_page?(inventory_index_path) %>"><a href="#">Menu</a></li>
I am using materialize css and my way of making the main categories collapsible is by using the code below
$('.active').closest(".collapsible.collapsible-accordion")
.find(".collapsible-header")
.click();
hope it helps someone
回答12:
The current_page?
method isn't flexible enough for me (say you set a controller but not an action, then it'll only return true on the controller's index action), so I've made this based on the other answers:
def nav_link_to(link_text, link_path, checks=nil)
active = false
if not checks.nil?
active = true
checks.each do |check,v|
if not v.include? params[check]
active = false
break
end
end
end
return content_tag :li, :class => (active ? 'active' : '') do
link_to link_text, link_path
end
end
Example:
nav_link_to "Pages", pages_url, :controller => 'pages'
回答13:
I have a more succinct version of nav_link that works exactly like link_to, but is customized to output a wrapping li tag.
Put the following in your application_helper.rb
def nav_link(*args, &block)
if block_given?
options = args.first || {}
html_options = args.second
nav_link(capture(&block), options, html_options)
else
name = args[0]
options = args[1] || {}
html_options = args[2]
html_options = convert_options_to_data_attributes(options, html_options)
url = url_for(options)
class_name = current_page?(url) ? 'active' : nil
href = html_options['href']
tag_options = tag_options(html_options)
href_attr = "href=\"#{ERB::Util.html_escape(url)}\"" unless href
"<li class=\"#{class_name}\"><a #{href_attr}#{tag_options}>#{ERB::Util.html_escape(name || url)}</a></li>".html_safe
end
end
If you look at the above code and compare it to the link_to code in url_helper.rb, the only difference is that it checks if the url is the current page, and adds the class "active" to a wrapping li tag. This is because I'm using the nav_link helper with Twitter Bootstrap's nav component which prefers links to be wrapped inside li tags and the "active" class applied to the outer li.
The nice thing about the above code is that it allows you to pass in a block into the function, just like you can do with link_to.
For example, a bootstrap nav list with icons would look like:
Slim:
ul.nav.nav-list
=nav_link root_path do
i.icon-home
| Home
=nav_link "#" do
i.icon-user
| Users
Output:
<ul class="nav nav-list">
<li class="active">
<a href="/">
<i class="icon-home"/>
Home
</a>
</li>
<li>
<a href="#">
<i class="icon-users"/>
Users
</a>
</li>
</ul>
In addition, just like the link_to helper, you can pass in HTML options into nav_link, which will be applied to the a tag.
An example of passing in a title for the anchor:
Slim:
ul.nav.nav-list
=nav_link root_path, title:"Home" do
i.icon-home
| Home
=nav_link "#", title:"Users" do
i.icon-user
| Users
Output:
<ul class="nav nav-list">
<li class="active">
<a href="/" title="Home">
<i class="icon-home"/>
Home
</a>
</li>
<li>
<a href="#" title="Users">
<i class="icon-users"/>
Users
</a>
</li>
</ul>
回答14:
Yep! Check out this article: A Better Way to Add a ‘selected’ Class to Links in Rails
Drop nav_link_helper.rb into app/helpers and it can be as easy as:
<%= nav_link 'My_Page', 'http://example.com/page' %>
The nav_link helper works just like the standard Rails link_to helper, but adds a 'selected' class to your link (or its wrapper) if certain criteria are met. By default, if the link's destination url is the same url as the url of the current page, a default class of 'selected' is added to the link.
There's a gist here: https://gist.github.com/3279194
UPDATE: This is now a gem: http://rubygems.org/gems/nav_link_to
回答15:
I use a simple helper like this for top level links so the /stories/my-story
page highlights the /stories
link
def nav_link text, url
active = (url == request.fullpath || (url != '/' && request.fullpath[0..(url.size-1)] == url))
"<li#{ active ? " class='selected'" : '' }><a href='#{url}'>#{text}</a></li>".html_safe
end
回答16:
Let me show my solution:
_header.html.erb:
<ul class="nav">
<%= nav_tabs(@tabs) %>
</ul>
application_helper.rb:
def nav_tabs(tabs=[])
html = []
tabs.each do |tab|
html << (content_tag :li, :class => ("current-page" if request.fullpath.split(/[\??]/)[0] == tab[:path]) do
link_to tab[:path] do
content_tag(:i, '', :class => tab[:icon]) +
tag(:br) +
"#{tab[:name]}"
end
end)
end
html.join.html_safe
end
application_controller.rb:
before_filter :set_navigation_tabs
private
def set_navigation_tabs
@tabs =
if current_user && manager?
[
{ :name => "Home", :icon => "icon-home", :path => home_index_path },
{ :name => "Portfolio", :icon => "icon-camera", :path => portfolio_home_index_path },
{ :name => "Contact", :icon => "icon-envelope-alt", :path => contact_home_index_path }
]
elsif current_user && client?
...
end
回答17:
According to the answer by Skilldrick, I'll change it to the following:
def nav_link(*args, &block)
is_active = current_page?(args[0]) || current_page?(args[1])
class_name = is_active ? 'active' : nil
content_tag(:li, class: class_name) do
link_to *args, &block
end
end
to make it much more useful.
回答18:
This version is based on @Skilldrick's one but allows you to add html content.
Thus, you can do:
nav_link "A Page", a_page_path
but also:
nav_link a_page_path do
<strong>A Page</strong>
end
or any other html content (you can add an icon for instance).
Here the helper is:
def nav_link(name = nil, options = nil, html_options = nil, &block)
html_options, options, name = options, name, block if block_given?
options ||= {}
html_options = convert_options_to_data_attributes(options, html_options)
url = url_for(options)
html_options['href'] ||= url
class_name = current_page?(url) ? 'current' : ''
content_tag(:li, :class => class_name) do
content_tag(:a, name || url, html_options, &block)
end
end
回答19:
I think I came up with a simple solution that might be helpful for a lot of use cases. This lets me:
- Support not only plain text but HTML inside
link_to
(e.g. add an icon inside the link)
- Add just few lines of code to
application_helper.rb
- Append
active
to the whole class name of the link element instead of it being the sole class.
So, add this to application_helper.rb
:
def active_class?(class_name = nil, path)
class_name ||= ""
class_name += " active" if current_page?(path)
class_name.strip!
return class_name
end
And on your template you can have something like this:
<div class="col-xs-3">
<%= link_to root_path, :class => active_class?("btn btn-outline-primary", root_path) do %>
<i class="fa fa-list-alt fa-fw"></i>
<% end %>
</div>
As bonus you can specify or not a class_name
and use it like this: <div class="<%= current_page?(root_path) %>">
Thanks to previous answers 1, 2 and resources.
回答20:
all these work with simple nav bars, but what about drop down sub-menu ?
when a sub-menu is selected the top menu item should be made 'current'
in this case tabs_on_rails me be the solution
回答21:
This is how I solved in my current project.
def class_if_current_page(current_page = {}, *my_class)
if current_page?(current_page)
my_class.each do |klass|
"#{klass} "
end
end
end
Then..
li = link_to company_path
class: %w{ class_if_current_page( { status: "pending" }, "active" ), "company" } do
Current Company
回答22:
My easy way -
application.html.erb
,
<div class="navbar">
<div class="<%= @menu1_current %> first-item"><a href="/menu1"> MENU1 </a></div>
<div class="<%= @menu2_current %>"><a href="/menu2"> MENU2 </a></div>
<div class="<%= @menu3_current %>"><a href="/menu3"> MENU3 </a></div>
<div class="<%= @menu4_current %> last-item"><a href="/menu4"> MENU4 </a></div>
</div>
main_controller.erb
,
class MainController < ApplicationController
def menu1
@menu1_current = "current"
end
def menu2
@menu2_current = "current"
end
def menu3
@menu3_current = "current"
end
def menu4
@menu4_current = "current"
end
end
Thanks.
回答23:
If also you want to support html options hash in the view. For example if you want to call it with other CSS class or id, you can define the helper function like this.
def nav_link_to(text, url, options = {})
options[:class] ||= ""
options[:class] += " active"
options[:class].strip!
link_to text, url, options
end
So in the view, call this helper the same way you'd call link_to helper
<%= nav_link_to "About", about_path, class: "my-css-class" %>
回答24:
Create a method in ApplicationHelper
as below.
def active controllers, action_names = nil
class_name = controllers.split(",").any? { |c| controller.controller_name == c.strip } ? "active" : ""
if class_name.present? && action_names.present?
return action_names.split(",").any? { |an| controller.action_name == an.strip } ? "active" : ""
end
class_name
end
Now use it in view as below use cases.
1. For all action of any specific controller
<li class="<%= active('controller_name')%>">
....
</li>
2. For all action of many controllers (with comma seperated)
<li class="<%= active('controller_name1,controller_name2')%>">
....
</li>
3. For specific action of any specific controller
<li class="<%= active('controller_name', 'action_name')%>">
....
</li>
4. For specific action of many controllers (with comma seperated)
<li class="<%= active('controller_name1,controller_name2', 'action_name')%>">
....
</li>
5. For some specific actions of any specific controller
<li class="<%= active('controller_name', 'index, show')%>">
....
</li>
6. For some specific actions of many controllers (with comma seperated)
<li class="<%= active('controller_name1,controller_name2', 'index, show')%>">
....
</li>
Hope it helps