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

구문의 간결함을 제외하고는 더 이상 이점이 없습니다. 다른 사람이 더 나은 솔루션을 가지고 있는지 궁금합니다.
Yannis

나는이 방법을 아주 성공적으로했다. 보기에 다음 코드를 추가했습니다. <% = link_to "Users", users_path, class : (controller? ( "users")? 'selected': nil) %> / users 및 / users / new 모두에서 작동한다는 점이 정말 깔끔합니다. .
Andreas

1
개선이 될 수 controller_nameaction_name아마 대신 PARAMS의
프란체스코 벨라

잘 했어. 나는 이것을 단순하게 유지하려고 생각하지 않았지만 이것은 매우 멋지게 확장됩니다. +1
newdark-it 2018

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
당신은 트위터 부트 스트랩 네비게이션 바 사용하는 경우이 트위터 ootstrap와 위대한 작품을 twitter.github.com/bootstrap/examples/hero.html
리 McAlilly

41
class_name = current_page? (link_path)로 변경 하시겠습니까? '현재'전무 당신은 클래스 태그를 표시하지 않으려면하지 않을 때 현재 페이지
마 후이

1
드롭 다운에 사용되는 중첩 목록에 대해 어떻게 수정 하시겠습니까?
doremi

9
사막으로 건조
올랜도

1
몇 가지 추가 인수 extra_classes = nil, id = nil을 추가 한 다음 content_tag content_tag (: li, class : [class_name, extra_classes], id : id) 안에 자신의 클래스와 id를 요소에 추가 할 수 있습니다. :)
Jon

72

current_page?도우미를 사용하여 "current"클래스를 할당해야하는지 여부를 결정합니다 . 예를 들면 :

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

경로 (옵션 해시뿐만 아니라)도 전달할 수 있습니다 current_page?(root_path). 예 : .


3
이것을 쿼리 매개 변수를 무시하는 방법이 있습니까?
Mohamad

@Mohamad, 당신은 이것을 할 수 있습니다 : current_page? (controller : 'users', action : 'index')
nilid

26

이 nav_link (text, 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 2013

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로 10 년 후에 이동)을 처음 접했기 때문에 이것이 중대한 결함이 있다면 듣고 싶습니다.

적어도 이렇게하면 각 링크에서 하나의 도우미 함수와 간단한 호출 만 필요합니다.


1
문제 일뿐입니다. request_uri 대신 request.path를 사용했습니다 (request_uri가 작동하지 않았거나 레일 버전 문제가 있습니까?). 당신의 대답은 제 생각에 깨끗하고 우아합니다.
Tony

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

빈 수업을 남겨도 괜찮습니까? ""
Harsha MV

예. 빈 클래스 속성이 많은 소스를 보면 이상하게 보일 수 있지만 유효한 HTML입니다.
코 발츠

을 사용할 수 있으며 <%= content_tag(:li, "Click me", class: is_active('controller', 'action')) %>nil에 대한 클래스 속성을 인쇄하지 않습니다. apidock.com/rails/ActionView/Helpers/TagHelper/content_tag
neonmate

4

나는 그것이 오래 된 대답이라는 것을 알고 있지만 active_link_to gem 이라는 link_to 도우미 래퍼를 사용하여 이러한 모든 현재 페이지 확인을 쉽게 무시할 수 있습니다. 원하는대로 정확하게 작동하고 현재 페이지 링크에 활성 클래스를 추가합니다.


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

link_to와 똑같이 작동하는 nav_link의 더 간결한 버전이 있지만 래핑 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 태그에 클래스 "active"를 추가한다는 것입니다. Twitter Bootstrap의 nav 구성 요소 와 함께 nav_link 도우미를 사용하고 있기 때문입니다. 링크가 li 태그 안에 래핑되고 외부 li에 적용된 "active"클래스를 선호하는 입니다.

위 코드의 좋은 점은 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>

대박. 나에게 이것은 블록을 허용하기 때문에 가장 실행 가능한 옵션이었습니다. 정말 감사합니다!
Kasperi

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

2

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'

답변 주셔서 감사합니다. 나는 당신이 실제로 허용 대답과 비슷합니다 :) 생각
PeterWong

나는이 문제가 된 이후 나는 도움말 : 물론이 우연히 만나는 모든 사람 줄 알았는데, 그래서 나는, Google을 통해이 대답 건너 온
unrelativity을

2

네! 이 기사를 확인하십시오 : Rails의 링크에 '선택된'클래스를 추가하는 더 나은 방법

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

업데이트 : 이것은 이제 gem입니다 : http://rubygems.org/gems/nav_link_to


이거 좋은데. 나는 사용하고 선택되지 않은 요소에 클래스 이름을 제공하는 것을 지원하도록 수정을 추가했습니다.
Teemu Leisti 2013

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>

도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.