Лучший способ добавить «текущий» класс для навигации в Rails 3 - PullRequest
110 голосов
/ 14 сентября 2010

У меня есть несколько статических страниц в меню навигации. Я хочу добавить класс типа «текущий» к элементу, который отображается в данный момент.

Я делаю так, чтобы добавить тонны вспомогательных методов (каждый для одного элемента) для проверки контроллера и действия.

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

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

Есть ли лучший способ сделать это !? Мой нынешний путь такой глупый ...

Ответы [ 24 ]

3 голосов
/ 07 июля 2016

Для меня лично я использовал комбинацию ответов здесь

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

Я использую материализовать CSS, и мой способ сделать основные категории разборными, используя код ниже

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

надеюсь, это кому-нибудь поможет

2 голосов
/ 08 ноября 2013

Позвольте мне показать мое решение:

_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
2 голосов
/ 22 сентября 2012

У меня есть более лаконичная версия 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

Если вы посмотрите на приведенный выше код и сравните его с кодом link_to в url_helper.rb, единственное отличие состоит в том, что он проверяет,URL-адрес является текущей страницей и добавляет класс «активный» в тег li для переноса.Это потому, что я использую помощник nav_link с компонентом nav Bootstrap Twitter Bootstrap , который предпочитает оборачивать ссылки внутри тегов li, а класс active применяется к внешнему li.

NiceЧто касается приведенного выше кода, это то, что он позволяет передавать блок в функцию, так же, как вы можете сделать это с link_to.

Например, список навигации при начальной загрузке со значками будет выглядеть так:

Slim:

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, который будет применен к тегу..

Пример передачи заголовка для якоря:

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

Вывод:

<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>
2 голосов
/ 08 августа 2012

Да!Прочтите эту статью: Лучший способ добавить «выбранный» класс к ссылкам в 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

2 голосов
/ 30 декабря 2011

Метод 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'
2 голосов
/ 14 августа 2013

Я использую простой помощник для ссылок верхнего уровня, поэтому на странице /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
1 голос
/ 11 ноября 2014

Эта версия основана на версии @ 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 голос
/ 08 января 2017

Я думаю, что придумал простое решение, которое может быть полезно для многих случаев использования. Это позволяет мне:

  • Поддержка не только простого текста, но и HTML внутри link_to (например, добавьте значок внутри ссылки)
  • Добавьте всего несколько строк кода к 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 и использовать его следующим образом: <div class="<%= current_page?(root_path) %>">

Благодаря предыдущим ответам 1 , 2 и ресурсы .

1 голос
/ 04 декабря 2013

Согласно ответу от 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

, чтобы сделать его намного более полезным.

0 голосов
/ 04 июля 2017

Создайте метод в 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>

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...