Rails 3で「現在の」クラスをナビゲーションに追加する最良の方法


111

ナビゲーションメニューにいくつかの静的ページがあります。現在表示しているアイテムに「current」のようなクラスを追加したい。

私がそうしている方法は、コントローラーとアクションをチェックするためのヘルパーメソッド(それぞれ1つのアイテム)を追加することです。

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 2010

構文の簡潔さを除けば、これ以上の利点はありません。他の誰かがより良い解決策を持っているかどうか知りたいです。
Yannis

私はこの方法を成功させました。次のコードをビューに追加しました:<%= link_to "Users"、users_path、class:(controller?( "users")? 'selected':nil)%>それは/ usersと/ users / newの両方で機能することを本当にきれいにしています。
Andreas 14

1
おそらく改善の可能性がcontroller_nameありaction_name、paramsの代わりに
Francesco Belladonna

よくやった。私はこれを単純に保つことを考えていませんでしたが、これは非常にうまくスケーリングします。+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ブートストラップnavbar twitter.github.com/bootstrap/examples/hero.html
Lee McAlilly

41
class_name = current_page?(link_path)に変更しますか?'current':現在のページにないときにクラスタグを表示したくない場合はnil
Matthew Hui

1
ドロップダウンで使用されるネストされたリストのこれをどのように変更しますか?
ドレミ2013

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、これを行うことができます:current_page?(controller: 'users'、action: 'index')
nilid

26

私はapplication_helper.rb(Rails 3)でこのnav_link(text、link)関数を使用して仕事を完了し、私のブートストラップtwitter 2.0 nav barリンクをロールバックします。

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つのヘルパー関数と単純な呼び出しのみが必要です。


1
ただ問題です。request_uriの代わりにrequest.pathを使用しました(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') %>">

空白のクラス ""をそのままにしても大丈夫ですか?
Harsha MV

はい。空のクラス属性の束を見てソースを表示すると奇妙に見えるかもしれませんが、それは有効なHTMLです。
kobaltz 2014

を使用できますが<%= content_tag(:li, "Click me", class: is_active('controller', 'action')) %>、nilのクラス属性は出力されません。apidock.com/rails/ActionView/Helpers/TagHelper/content_tag
neonmate

4

私はそれが古い回答であることを知っていますが、active_link_toと呼ばれるlink_toヘルパーラッパーを使用することで、これらすべての現在のページチェックを簡単に無視できます gem、それはあなたが望むとおりに機能し、現在のページリンクにアクティブクラスを追加します


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

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タグに追加することです。これは、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に渡して、タグに適用できます。

アンカーのタイトルを渡す例:

スリム:

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、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?メソッドは私にとって十分な柔軟性を備えていません(たとえば、コントローラーを設定したがアクションは設定しなかった場合、コントローラーのインデックスアクションでのみ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をapp / helpersにドロップすると、次のように簡単にできます。

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

nav_linkヘルパーは、標準のRails link_toヘルパーと同じように機能しますが、特定の基準が満たされた場合、「選択された」クラスをリンク(またはそのラッパー)に追加します。デフォルトでは、リンクのリンク先URLが現在のページのURLと同じ場合、デフォルトのクラス「選択済み」がリンクに追加されます。

ここに要点があります:https//gist.github.com/3279194

更新:これは今宝石です: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>

おまけとして、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オプションのハッシュもサポートする場合は、たとえば、他の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.