在Rails 3中将“当前”类添加到导航的最佳方法


111

我在导航菜单中有一些静态页面。我想向当前显示的项目添加一个类似“当前”的类。

我这样做的方法是添加大量的辅助方法(每个辅助方法一项)来检查控制器和操作。

def current_root_class
  'class="current"' if controller_name == "homepage" && action_name == "index" 
end

<ul>
  <li <%= current_root_class %>><%= link_to "Home", root_path %>

有没有更好的方法!?我目前的方式是如此愚蠢……

Answers:


56

这里并不是真正的答案,因为我使用的方式与您完全相同。我刚刚定义了辅助方法来测试多个控制器或动作:

在application_helper.rb中

  def controller?(*controller)
    controller.include?(params[:controller])
  end

  def action?(*action)
    action.include?(params[:action])
  end

然后,您可以if controller?("homepage") && action?("index", "show")在自己的视图中使用其他辅助方法...


当某些页面由不同的控制器/操作处理但在同一菜单项中时,您的方式最合适?您是否遇到了更多优势〜?
PeterWong

除了语法的简洁之外,没有其他优势。我很好奇,看看其他人是否有更好的解决方案。
Yannis 2010年

我成功地完成了这种方法。将此代码添加到视图中:<%= link_to“ Users”,users_path,类:(controller?(“ users”)?'selected':nil)%>十分巧妙,它既适用于/ users也适用于/ users / new 。
Andreas

1
可能是一种改进controller_nameaction_name而不是可能的改进
Francesco Belladonna 2014年

做得好。我没想到要保持简单,但是可以很好地扩展。+1
newdark-it

290

我做了一个助手,叫做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

像这样使用:

nav_link 'Home', root_path

会产生像

<li class="current"><a href="/">Home</a></li>

3
如果您使用的是twitter bootstrap导航栏,那么它与twitter ootstrap搭配使用效果很好twitter.github.com/bootstrap/examples/hero.html
Lee McAlilly,2012年

41
更改为class_name = current_page?(link_path)?'current':如果您不希望当不在当前页面上时不显示class标记,则为nil
Matthew Hui

1
您如何修改下拉列表中使用的嵌套列表?
doremi

9
沙漠干燥
奥兰多

1
我添加了一些额外的参数extra_classes = nil,id = nil,然后在content_tag content_tag(:li,class:[class_name,extra_classes],id:id)内,以便您也可以向元素添加自己的类和id :)
2015年

72

使用current_page?帮助程序来确定是否应分配"current"课程。例如:

<%= 'active' if current_page?(home_about_path) %>

请注意,您还可以传递路径(不仅是选项的哈希),例如:current_page?(root_path)


3
有没有办法让它忽略查询参数?
穆罕默德

@Mohamad,您可以执行以下操作:current_page?(控制器:“用户”,操作:“索引”)
nilid

26

我在application_helper.rb(Rails 3)中使用此nav_link(text,link)函数来完成工作,它为我滚动了bootstrap twitter 2.0导航栏链接。

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

例:

<%=nav_link("About Us", about_path) %>

可以current_page?像其他答案中那样,通过使用该方法进行简化。
Teemu Leisti

10

我这样做的方法是在application_helper中添加一个辅助函数

def current_class?(test_path)
  return 'current' if request.request_uri == test_path
  ''
end

然后在导航中

<%= link_to 'Home', root_path, :class => current_class?(root_path) %>

这将针对当前页面uri测试链接路径,并返回当前类或空字符串。

我还没有对它进行彻底的测试,而且我对RoR还是很陌生(使用PHP十年后已经搬迁了),因此,如果它有重大缺陷,我希望听听。

至少通过这种方式,每个链接仅需要1个辅助函数和一个简单调用。


1
只是一个问题。我使用了request.path而不是request_uri(request_uri无法正常工作,也许是Rails版本问题?)。我认为您的回答干净而优雅。
托尼

6

建立@Skilldrick的答案...

如果将此代码添加到application.js,它将确保所有具有活动子项的下拉菜单也将被标记为活动...

$('.active').closest('li.dropdown').addClass('active');

回顾支持代码>添加一个名为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

像这样使用:

nav_link_to 'Home', root_path

会产生像

<li class="active"><a href="/">Home</a></li>

4

我认为最好的方法是

application_helper.rb:

def is_active(controller, action)       
  params[:action] == action && params[:controller] == controller ? "active" : nil        
end

在菜单中:

<li class="<%= is_active('controller', 'action') %>">

这样可以留空类吗?”可以吗?
Harsha MV 2014年

是。如果您在查看源代码时看到一堆空的类属性,则可能看起来很奇怪,但这是有效的HTML。
kobaltz 2014年

您可以使用<%= content_tag(:li, "Click me", class: is_active('controller', 'action')) %>,但不会显示nil的类属性。apidock.com/rails/ActionView/Helpers/TagHelper/content_tag
霓虹灯

4

我知道这是一个过时的答案,但是您可以使用一个名为active_link_to gem 的link_to帮助器包装轻松地忽略所有这些当前页面检查,它可以按您想要的方式工作,将一个活动类添加到当前页面链接中


4

这是完整的示例,说明如何在Rails视图的引导菜单页面上添加活动类。

    <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>


3

我有一个更简洁的nav_link版本,其功能与link_to完全相同,但已被定制为输出包装的li标签。

将以下内容放入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

如果查看上面的代码并将其与url_helper.rb中的link_to代码进行比较,则唯一的区别是它将检查url是否为当前页面,并将“活动”类添加到包装的li标记中。这是因为我将nav_link帮助器与Twitter Bootstrap的nav组件一起使用更喜欢将链接包装在li标记内,并将“活动”类应用于外部li。

上面的代码的好处是,它允许您将一个块传递到函数中,就像可以使用link_to一样。

例如,带有图标的引导导航列表如下所示:

瘦:

ul.nav.nav-list
  =nav_link root_path do
    i.icon-home
    |  Home
  =nav_link "#" do
    i.icon-user
    |  Users

输出:

<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>

此外,就像link_to助手一样,您可以将HTML选项传递到nav_link中,该选项将应用于a标签。

传递锚标题的示例:

瘦:

ul.nav.nav-list
  =nav_link root_path, title:"Home" do
    i.icon-home
    |  Home
  =nav_link "#", title:"Users" do
    i.icon-user
    |  Users

输出:

<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>

太棒了 对我来说,这是最可行的选择,正是因为它允许使用块。万分感谢!
卡斯佩里2014年

3

就我个人而言,我在这里使用了多种答案

<li class="<%= 'active' if current_page?(inventory_index_path) %>"><a href="#">Menu</a></li>

我正在使用物化css,而使主要类别可折叠的方法是使用以下代码

$('.active').closest(".collapsible.collapsible-accordion")
            .find(".collapsible-header")
            .click();

希望它可以帮助某人


忘了这个。感谢您发布此提醒。
newdark-it

2

current_page?方法对我来说不够灵活(例如,您设置了一个控制器而不是一个动作,那么它只会在控制器的index动作上返回true),因此我根据其他答案进行了此设置:

  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

例:

nav_link_to "Pages", pages_url, :controller => 'pages'

谢谢您的回答。我认为您的答案实际上与已接受的答案类似:)
PeterWong 2011年

自从遇到问题以来,我就通过Google遇到了这个问题,所以我想我也会帮助遇到此问题的其他所有人:)
2011年

2

是的 查看本文:向Rails中的链接添加“选定”类的更好方法

将nav_link_helper.rb放到app / helpers中,它可以很简单:

<%= nav_link 'My_Page', 'http://example.com/page' %>

nav_link帮助程序的工作方式与标准Rails link_to帮助程序相同,但是如果满足某些条件,则将“选定的”类添加到您的链接(或其包装)中。默认情况下,如果链接的目标URL与当前页面的URL是相同的URL,则将默认类“ selected”添加到链接。

这里有一个要点:https : //gist.github.com/3279194

更新:这现在是一颗宝石:http : //rubygems.org/gems/nav_link_to


很好 我开始使用它,并添加了一个修改以支持为未选择的元素提供类名,也作为要点中的注释。
Teemu Leisti

2

我为顶层链接使用了这样的简单帮助程序,因此/stories/my-story页面突出显示了/stories链接

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

2

让我展示我的解决方案:

_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

1

根据Skilldrick回答,我将其更改为以下内容:

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

使它更加有用。


1

此版本基于@Skilldrick的版本,但允许您添加html内容。

因此,您可以执行以下操作:

nav_link "A Page", a_page_path

但是也:

nav_link a_page_path do
  <strong>A Page</strong>
end

或任何其他html内容(例如,您可以添加图标)。

这里的助手是:

  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

1

我想我想出了一个简单的解决方案,可能对很多用例有用。这让我:

  • 不仅支持纯文本,还支持HTML link_to(例如,在链接内部添加图标)
  • 只需添加几行代码即可 application_helper.rb
  • 附加active到link元素的整个类名,而不是唯一的类。

因此,将其添加到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

在模板上,您可以像这样:

<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>

作为奖励,您可以指定a或不指定a class_name,如下所示使用它:<div class="<%= current_page?(root_path) %>">

由于以前的答案12资源


0

所有这些都可以通过简单的导航栏来使用,但是下拉子菜单呢?选择子菜单时,应将顶部菜单项设置为“当前”,在这种情况下,tabs_on_rails是解决方案


0

这就是我在当前项目中解决的方法。

def class_if_current_page(current_page = {}, *my_class)
    if current_page?(current_page)
      my_class.each do |klass|
        "#{klass} "
      end
    end
  end

然后..

li = link_to company_path 
    class: %w{ class_if_current_page( { status: "pending" }, "active" ), "company" } do  
      Current Company

0

我简单的方法-

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

谢谢。


0

如果您还想在视图中支持html options hash。例如,如果要使用其他CSS类或ID调用它,则可以定义这样的辅助函数。

def nav_link_to(text, url, options = {})
  options[:class] ||= ""
  options[:class] += " active"
  options[:class].strip!
  link_to text, url, options
end

因此,在视图中,以与调用link_to helper相同的方式调用此帮助器

<%= nav_link_to "About", about_path, class: "my-css-class" %>

0

ApplicationHelper下面创建一个方法。

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

现在,在以下用例中使用它。

1.对于任何特定控制器的所有动作

<li class="<%= active('controller_name')%>">
....
</li>

2.用于许多控制器的所有动作(逗号分隔)

<li class="<%= active('controller_name1,controller_name2')%>">
....
</li>

3.对于任何特定控制器的特定动作

<li class="<%= active('controller_name', 'action_name')%>">
....
</li>

4.对于许多控制器的特定操作(逗号分隔)

<li class="<%= active('controller_name1,controller_name2', 'action_name')%>">
....
</li>

5.对于任何特定控制器的某些特定动作

<li class="<%= active('controller_name', 'index, show')%>">
....
</li>

6.对于许多控制器的某些特定操作(用逗号分隔)

<li class="<%= active('controller_name1,controller_name2', 'index, show')%>">
....
</li>

希望能帮助到你

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.