Найкращий спосіб додати «поточний» клас до навичок у Rails 3


111

У мене в навігаційному меню є кілька статичних сторінок. Я хочу додати такий клас, як "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 %>

Чи є кращий спосіб зробити це !? Мій сучасний спосіб такий дурний ......

Відповіді:


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

Немає більшої переваги, крім лаконічності синтаксису. Мені цікаво побачити, чи є хтось інший кращого рішення.
— Янніс

Я зробив цей метод з великим успіхом. Додано цей код до подання: <% = link_to "Користувачі", users_path, class: (контролер? ("Користувачі")? 'Вибрано': nil)%> Дійсно, що він працює як для / користувачів, так і для користувачів / нових .
— Андреас

1
поліпшення може бути, controller_nameа action_nameзамість парамів, мабуть,
— Франческо Беладонна

Молодці. Я не думав зберігати це просто, але ця шкала дуже гарно. +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

який створить HTML на зразок

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

3
Це чудово працює з twitter ootstrap, якщо ви використовуєте завантажувач twitter bootstrap navbar twitter.github.com/bootstrap/examples/hero.html
— Lee McAlilly

41
Змінити на class_name = current_page? (Link_path)? 'current': нуль, якщо ви не хочете, щоб тег класу відображався, коли його немає на поточній сторінці
— Matthew Hui

1
Як би ви змінили це для вкладених списків, що використовуються у спадному меню?
— doremi

9
СУХАЙТЕ як пустеля
— Орландо

1
Я додав кілька додаткових аргументів extra_classes = nil, id = nil тоді всередині content_tag content_tag (: li, class: [class_name, extra_classes], id: id), щоб ви могли додавати власні класи та id до елементів. :)
— Джон

72

За допомогою current_page?помічника визначте, чи слід призначати "current"клас чи ні . Наприклад:

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

Зверніть увагу , ви також можете пройти шлях (не тільки хеш опцій), наприклад: current_page?(root_path).


3
Чи є спосіб отримати це, щоб ігнорувати параметри запитів?
— Мохамад

@Mohamad, ти можеш це зробити: current_page? (Контролер: 'users', action: 'index')
— nilid

26

Я використовую цю функцію nav_link (текст, посилання) в application_helper.rb (Rails 3), щоб виконати роботу, і вона перекочує мій завантажувальний 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

Потім у nav,

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

який створить HTML на зразок

<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') %>">

чи добре залишати порожній клас "" таким?
— Харша М. В.

Так. Це може виглядати дивно, якщо ви переглядаєте джерело, яке бачить купу порожніх атрибутів класу, але це дійсний HTML.
— кобальц

Ви можете використовувати <%= content_tag(:li, "Click me", class: is_active('controller', 'action')) %>, він не буде друкувати атрибут класу для nil. apidock.com/rails/ActionView/Helpers/TagHelper/content_tag
— неоновий

4

Я знаю, що це застаріла відповідь, але ви можете легко проігнорувати всі ці поточні перевірки сторінки, скориставшись допоміжною обгорткою link_to під назвою active_link_to gem, вона працює саме так, як ви хочете, додайте активний клас до посилання на поточну сторінку


4

Ось повний приклад того, як додати активний клас на сторінку меню завантажувального вікна в режимі подання рейлів.

    <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

Я використовую приголомшливий дорогоцінний камінь під назвою Tabs on Rails .


1
Дякую за пропозицію. Оскільки мій навичок настільки простий і є лише один з невеликими предметами, дорогоцінний камінь, ймовірно, перевантажений живленням.
— PeterWong

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

Якщо ви подивитеся на наведений вище код і порівняєте його з кодом link_to в url_helper.rb, різниця полягає лише в тому, що він перевіряє, чи є URL-адресою поточну сторінку, і додає клас "активний" до обгорткового тегу li. Це тому, що я використовую помічник nav_link з навігаційним компонентом Twitter Bootstrap який надає перевагу загортанню посилань всередині тегів li та класу "active", застосованого до зовнішнього 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, який буде застосовано до тегу.

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

Тонкий:

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>

Дивовижно. Для мене це був найбільш життєздатний варіант саме тому, що він дозволяє блокувати. Дякую тонну!
— Каспер

3

Для мене особисто я використав комбінацію відповідей

<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();

сподіваюся, що це комусь допоможе


забув про це. Дякуємо, що опублікували це як нагадування.
— newdark-це

2

current_page?Метод не є достатньо гнучким для мене (скажімо , ви встановили контролер , але не дія, то він буде повертати істину лише на вказівному дії контролера), так що я зробив це на основі інших відповідей:

  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

Я натрапив на цю відповідь через Google, оскільки у мене була ця проблема, тому я подумав, що допоможу і всім іншим, хто стикається з цим :)
— нереальність

2

Так! Перегляньте цю статтю: Кращий спосіб додати "вибраний" клас до посилань у рейках

Завантажте nav_link_helper.rb у додаток / помічники, і це може бути так само просто, як:

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

Помічник nav_link працює так само, як і стандартний помічник Rails link_to, але додає клас "вибраний" до вашого посилання (або його обгортки), якщо певні критерії виконуються. За замовчуванням, якщо URL-адреса посилання є тим же URL-адресом, що і URL-адреса поточної сторінки, до посилання додається клас "вибраний" за замовчуванням.

Тут є суть: 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до всього класу ім'я елемента посилання, а не єдиного класу.

Отже, додайте це до 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 та ресурсам .


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 параметри хеша у представленні. Наприклад, якщо ви хочете викликати його за допомогою іншого класу 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" %>

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>

Сподіваюся, це допомагає

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.