【问题标题】:Best way to add "current" class to nav in Rails 3在 Rails 3 中将“当前”类添加到导航的最佳方法
【发布时间】:2011-04-11 23:28:08
【问题描述】:

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

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

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

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

有没有更好的方法呢!?我现在的方式太傻了……

【问题讨论】:

    标签: navigation ruby-on-rails-3


    【解决方案1】:

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

    这将产生类似 HTML

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

    【讨论】:

    • 您如何以 DRY 的方式将其扩展到许多其他类/页面?为我的问题寻找一个优雅的答案:stackoverflow.com/questions/7760050/…
    • 如果您使用 twitter 引导导航栏 twitter.github.com/bootstrap/examples/hero.html,这对 twitter ootstrap 非常有效
    • 更改为 class_name = current_page?(link_path) ? 'current' : 如果您不想在当前页面上显示类标签,则为 nil
    • 对于下拉列表中使用的嵌套列表,您将如何修改它?
    • 我添加了一些额外的参数 extra_classes=nil, id=nil 然后在 content_tag content_tag(:li, class: [class_name, extra_classes], id: id) 这样你就可以添加你自己的元素的类和 id 也是如此:)
    【解决方案2】:

    使用current_page? 帮助器来确定是否应该分配"current" 类。例如:

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

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

    【讨论】:

    • 有没有办法让它忽略查询参数?
    • @Mohamad,你可以这样做:current_page?(controller: 'users', action: 'index')
    【解决方案3】:

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

    在 application_helper.rb 中

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

    然后你可以在你的视图中使用if controller?("homepage") &amp;&amp; action?("index", "show")或者其他辅助方法……

    【讨论】:

    • 当有一些页面由不同的控制器/动作处理但在同一个菜单项中时,你的方式最适合,对吧?有没有遇到更多的优势呢~?
    • 除了语法简洁之外没有其他优势。我很想知道其他人是否有更好的解决方案。
    • 我用这个方法取得了巨大的成功。将此代码添加到视图中: 非常简洁,它适用于 /users 和 /users/new .
    • 改进可能是controller_nameaction_name 而不是params 可能
    • 干得好。我没想过要保持这个简单,但这可以很好地扩展。 +1
    【解决方案4】:

    我在 application_helper.rb (Rails 3) 中使用这个 nav_link(text, link) 函数来完成工作,它会为我滚动我的引导 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? 方法来简化,就像其他答案一样。
    【解决方案5】:

    我的做法是在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 个辅助函数和每个链接中的简单调用。

    【讨论】:

    • 只是个问题。我使用 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
    

    这将产生类似 HTML

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

    【讨论】:

      【解决方案7】:

      我认为最好的方法是

      application_helper.rb:

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

      在菜单中:

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

      【讨论】:

      • 这样可以留空班吗?
      • 是的。如果您查看源代码时看到一堆空的类属性,这可能看起来很奇怪,但它是有效的 HTML。
      • 你可以使用&lt;%= content_tag(:li, "Click me", class: is_active('controller', 'action')) %&gt;,它不会打印nil的类属性。 apidock.com/rails/ActionView/Helpers/TagHelper/content_tag
      【解决方案8】:

      我知道这是一个过时的答案,但是您可以通过使用名为 active_link_to gem 的 link_to 辅助包装器轻松忽略所有这些当前页面检查,它完全符合您的要求,向当前页面链接添加一个活动类

      【讨论】:

        【解决方案9】:

        这里是完整的例子,关于如何在 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>
        

        【讨论】:

          【解决方案10】:

          我使用了一个很棒的 gem,叫做 Tabs on Rails

          【讨论】:

          • 感谢您的建议。由于我的导航非常简单,而且只有一个带有少量物品的导航,因此宝石可能会过度供电。
          【解决方案11】:

          我有一个更简洁的 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 component 一起使用,它更喜欢将链接包裹在 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>
          

          【讨论】:

          • 太棒了。对我来说,这是最可行的选择,因为它允许阻止。非常感谢!
          【解决方案12】:

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

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

          我正在使用 materialize css,我使主要类别可折叠的方法是使用下面的代码

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

          希望对某人有所帮助

          【讨论】:

          • 忘记了这一点。感谢您发布此提醒。
          【解决方案13】:

          current_page? 方法对我来说不够灵活(假设你设置了一个控制器但没有设置一个动作,那么它只会在控制器的索引动作上返回 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'
          

          【讨论】:

          • 感谢您的回答。我认为你的答案实际上与接受的答案相似:)
          • 因为我遇到了这个问题,所以我通过谷歌找到了这个答案,所以我想我也会帮助遇到这个问题的其他人:)
          【解决方案14】:

          是的!看看这篇文章:A Better Way to Add a ‘selected’ Class to Links in Rails

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

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

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

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

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

          【讨论】:

          • 这很好。我开始使用,并添加了一个修改以支持为未选择的元素提供类名,也作为要点中的注释。
          【解决方案15】:

          我对顶级链接使用这样的简单助手,因此/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
          

          【讨论】:

            【解决方案16】:

            让我展示一下我的解决方案:

            _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】:

              根据answer by 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
              

              让它更有用。

              【讨论】:

                【解决方案18】:

                此版本基于 @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
                

                【讨论】:

                  【解决方案19】:

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

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

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

                  作为奖励,您可以指定或不指定class_name 并像这样使用它:&lt;div class="&lt;%= current_page?(root_path) %&gt;"&gt;

                  感谢之前的回答 12resources

                  【讨论】:

                    【解决方案20】:

                    所有这些都适用于简单的导航栏,但是下拉子菜单呢? 选择子菜单时,顶部菜单项应制作“当前” 在这种情况下 tabs_on_rails 我是解决方案

                    【讨论】:

                      【解决方案21】:

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

                      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
                      

                      【讨论】:

                        【解决方案22】:

                        我的简单方法 -

                        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
                        

                        谢谢。

                        【讨论】:

                          【解决方案23】:

                          如果您还想在视图中支持 html 选项哈希。例如,如果你想用其他 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 助手的方式相同

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

                          【讨论】:

                            【解决方案24】:

                            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>
                            

                            希望对你有帮助

                            【讨论】:

                              猜你喜欢
                              • 2021-11-16
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2015-10-18
                              • 1970-01-01
                              相关资源
                              最近更新 更多