Cara terbaik untuk menambahkan kelas "saat ini" ke navigasi di Rails 3


111

Saya memiliki beberapa halaman statis di menu navigasi. Saya ingin menambahkan kelas seperti "saat ini" ke item yang sedang ditampilkan.

Cara saya melakukannya adalah dengan menambahkan banyak metode pembantu (masing-masing untuk satu item) untuk memeriksa pengontrol dan tindakan.

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

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

Apakah ada cara yang lebih baik untuk melakukannya !? Cara saya saat ini sangat bodoh ...

Jawaban:


56

Bukan jawaban yang sebenarnya di sini, karena saya menggunakan cara yang sama seperti Anda. Saya baru saja menetapkan metode pembantu untuk menguji beberapa pengontrol atau tindakan:

Dalam application_helper.rb

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

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

Kemudian Anda dapat menggunakan if controller?("homepage") && action?("index", "show")di tampilan Anda atau metode pembantu lainnya…


Cara Anda paling sesuai ketika ada beberapa halaman yang ditangani oleh pengontrol / tindakan yang berbeda tetapi dalam item menu yang sama, bukan? Apakah Anda menemukan lebih banyak keuntungan ~?
PeterWong

Tidak ada lagi keuntungan kecuali keringkasan sintaks. Saya ingin tahu apakah ada orang lain yang memiliki solusi yang lebih baik.
Yannis

Saya melakukan metode ini dengan sukses besar. Menambahkan kode ini ke tampilan: <% = link_to "Users", users_path, class: (controller? ("Users")? 'Selected': nil)%> Benar-benar rapi sehingga berfungsi untuk / users dan / users / new .
Andreas

1
sebuah perbaikan bisa terjadi controller_namedan mungkin action_namebukannya params
Francesco Belladonna

Sudah selesai dilakukan dengan baik. Saya tidak berpikir untuk membuat ini sederhana tetapi timbangan ini sangat bagus. +1
newdark-it

290

Saya membuat seorang pembantu menelepon 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

digunakan seperti:

nav_link 'Home', root_path

yang akan menghasilkan HTML seperti

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

3
Ini berfungsi baik dengan twitter ootstrap jika Anda menggunakan navbar bootstrap twitter twitter.github.com/bootstrap/examples/hero.html
Lee McAlilly

41
Ubah ke class_name = current_page? (Link_path)? 'saat ini': nihil jika Anda tidak ingin tag kelas ditampilkan ketika tidak ada di halaman saat ini
Matthew Hui

1
Bagaimana Anda akan memodifikasi ini untuk daftar bersarang yang digunakan di dropdown?
doremi

9
KERING seperti gurun
Orlando

1
Saya telah menambahkan beberapa argumen tambahan extra_classes = nil, id = nil lalu di dalam content_tag content_tag (: li, class: [class_name, extra_classes], id: id) sehingga Anda dapat menambahkan kelas dan id Anda sendiri ke elemen juga :)
Jon

72

Gunakan current_page?helper untuk menentukan apakah Anda harus menetapkan "current"kelas atau tidak . Sebagai contoh:

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

Catatan Anda juga dapat melewati jalan (bukan hanya hash pilihan), misalnya: current_page?(root_path).


3
Apakah ada cara untuk mendapatkan ini dengan mengabaikan parameter kueri?
Mohamad

@Mohamad, Anda dapat melakukan ini: current_page? (Controller: 'users', action: 'index')
nilid

26

Saya menggunakan fungsi nav_link (teks, tautan) ini di application_helper.rb (Rails 3) untuk menyelesaikan pekerjaan dan itu memutar tautan bar nav bootstrap twitter 2.0 saya untuk saya.

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

Contoh:

<%=nav_link("About Us", about_path) %>

Ini dapat disederhanakan dengan menggunakan current_page?metode, seperti pada jawaban lain.
Teemu Leisti

10

Cara saya melakukannya adalah dengan menambahkan fungsi pembantu di application_helper

def current_class?(test_path)
  return 'current' if request.request_uri == test_path
  ''
end

Kemudian di nav,

<%= link_to 'Home', root_path, :class => current_class?(root_path) %>

Ini menguji jalur link terhadap halaman saat ini uri dan mengembalikan kelas Anda saat ini atau string kosong.

Saya belum menguji ini secara menyeluruh dan saya sangat baru mengenal RoR (pindah setelah satu dekade dengan PHP) jadi jika ini memiliki kelemahan utama, saya ingin mendengarnya.

Setidaknya dengan cara ini Anda hanya membutuhkan 1 fungsi pembantu dan satu panggilan sederhana di setiap tautan.


1
Hanya masalah. Saya menggunakan request.path daripada request_uri (request_uri tidak berfungsi, mungkin masalah versi rails?). Jawaban Anda bersih dan elegan menurut saya.
Tony

6

Untuk membangun jawaban @Skilldrick ...

Jika Anda menambahkan kode ini ke application.js, itu akan memastikan bahwa setiap menu dropdown dengan anak-anak yang aktif juga akan ditandai sebagai aktif ...

$('.active').closest('li.dropdown').addClass('active');

Untuk merekap kode pendukung> Tambahkan pembantu yang disebut 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

digunakan seperti:

nav_link_to 'Home', root_path

yang akan menghasilkan HTML seperti

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

4

Saya pikir cara terbaik adalah

application_helper.rb:

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

Dan di menu:

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

tidak apa-apa meninggalkan kelas "" kosong seperti itu?
Harsha MV

Iya. Mungkin terlihat aneh jika Anda melihat sumber melihat sekumpulan atribut kelas kosong, tetapi itu adalah HTML yang valid.
kobaltz

Anda dapat menggunakan <%= content_tag(:li, "Click me", class: is_active('controller', 'action')) %>, itu tidak akan mencetak atribut kelas untuk nil. apidock.com/rails/ActionView/Helpers/TagHelper/content_tag
neonmate

4

Saya tahu ini adalah jawaban yang sudah ketinggalan zaman , tetapi Anda dapat dengan mudah mengabaikan semua pemeriksaan halaman saat ini dengan menggunakan pembungkus link_to helper, yang disebut permata active_link_to , berfungsi persis seperti yang Anda inginkan, tambahkan kelas aktif ke tautan halaman saat ini


4

Berikut adalah contoh lengkapnya, tentang cara menambahkan kelas aktif pada halaman menu bootstrap dalam tampilan rel.

    <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

Saya menggunakan permata mengagumkan yang disebut Tabs on Rails .


1
Terima kasih untuk sarannya. Karena navigasi saya sangat sederhana dan hanya ada satu dengan item kecil, permata itu mungkin akan terlalu bertenaga.
PeterWong

3

Saya memiliki versi nav_link yang lebih ringkas yang bekerja persis seperti link_to, tetapi disesuaikan untuk mengeluarkan tag li pembungkus.

Letakkan baris berikut di application_helper.rb Anda

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

Jika Anda melihat kode di atas dan membandingkannya dengan kode link_to di url_helper.rb, satu-satunya perbedaan adalah ia memeriksa apakah url adalah halaman saat ini, dan menambahkan kelas "aktif" ke tag li pembungkus. Ini karena saya menggunakan pembantu nav_link dengan komponen nav Twitter Bootstrap yang lebih memilih tautan untuk dibungkus di dalam tag li dan kelas "aktif" diterapkan ke li luar.

Hal yang menyenangkan tentang kode di atas adalah memungkinkan Anda memasukkan blok ke dalam fungsi, seperti yang dapat Anda lakukan dengan link_to.

Misalnya, daftar navigasi bootstrap dengan ikon akan terlihat seperti ini:

Ramping:

ul.nav.nav-list
  =nav_link root_path do
    i.icon-home
    |  Home
  =nav_link "#" do
    i.icon-user
    |  Users

Keluaran:

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

Selain itu, seperti helper link_to, Anda dapat memasukkan opsi HTML ke nav_link, yang akan diterapkan ke tag.

Contoh penyampaian judul untuk jangkar:

Ramping:

ul.nav.nav-list
  =nav_link root_path, title:"Home" do
    i.icon-home
    |  Home
  =nav_link "#", title:"Users" do
    i.icon-user
    |  Users

Keluaran:

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

Mengagumkan. Bagi saya ini adalah opsi yang paling tepat karena memungkinkan blok. Terima kasih banyak!
Kasperi

3

Bagi saya pribadi, saya menggunakan kombinasi jawaban di sini

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

Saya menggunakan materialize css dan cara saya membuat kategori utama dilipat adalah dengan menggunakan kode di bawah ini

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

semoga bisa membantu seseorang


lupakan tentang ini. Terima kasih telah memposting ini sebagai pengingat.
newdark-it

2

The current_page?Metode tidak cukup fleksibel untuk saya (mengatakan Anda mengatur controller tapi tidak tindakan, maka hanya akan kembali benar pada tindakan indeks controller), jadi saya sudah membuat ini berdasarkan jawaban yang lain:

  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

Contoh:

nav_link_to "Pages", pages_url, :controller => 'pages'

Terima kasih atas jawaban Anda. Saya pikir jawaban Anda mirip dengan jawaban yang diterima sebenarnya :)
PeterWong

Saya menemukan jawaban ini melalui Google karena saya mengalami masalah ini, jadi saya pikir saya akan membantu semua orang yang menemukan ini juga :)
unrelativitas

2

Ya! Lihat artikel ini: Cara yang Lebih Baik untuk Menambahkan Kelas 'terpilih' ke Tautan di Rails

Letakkan nav_link_helper.rb ke dalam app / helpers dan itu bisa semudah:

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

Helper nav_link bekerja seperti pembantu link_to Rails standar, tetapi menambahkan kelas 'terpilih' ke tautan Anda (atau pembungkusnya) jika kriteria tertentu terpenuhi. Secara default, jika url tujuan tautan adalah url yang sama dengan url laman saat ini, kelas default 'dipilih' ditambahkan ke tautan.

Ada intinya di sini: https://gist.github.com/3279194

UPDATE: Sekarang ini adalah permata: http://rubygems.org/gems/nav_link_to


Ini bagus. Saya mulai menggunakannya, dan menambahkan modifikasi untuk mendukung pemberian nama kelas ke elemen yang tidak dipilih, juga, sebagai komentar di intinya.
Teemu Leisti

2

Saya menggunakan penolong sederhana seperti ini untuk tautan tingkat atas sehingga /stories/my-storyhalaman menyoroti /storiestautan tersebut

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

Izinkan saya menunjukkan solusi saya:

_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

Menurut jawaban dari Skilldrick , saya akan mengubahnya menjadi yang berikut:

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

agar lebih bermanfaat.


1

Versi ini didasarkan pada versi @ Skilldrick tetapi memungkinkan Anda untuk menambahkan konten html.

Dengan demikian, Anda dapat melakukan:

nav_link "A Page", a_page_path

tetapi juga:

nav_link a_page_path do
  <strong>A Page</strong>
end

atau konten html lainnya (Anda dapat menambahkan ikon misalnya).

Di sini penolongnya adalah:

  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

Saya rasa saya menemukan solusi sederhana yang mungkin berguna untuk banyak kasus penggunaan. Ini memungkinkan saya:

  • Mendukung tidak hanya teks biasa tetapi HTML di dalamnya link_to(misalnya menambahkan ikon di dalam tautan)
  • Tambahkan hanya beberapa baris kode ke application_helper.rb
  • Tambahkan activeke seluruh nama kelas dari elemen tautan alih-alih menjadi satu-satunya kelas.

Jadi, tambahkan ini ke 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

Dan pada template Anda, Anda dapat memiliki sesuatu seperti ini:

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

Sebagai bonus, Anda dapat menentukan atau tidak class_namedan menggunakannya seperti ini:<div class="<%= current_page?(root_path) %>">

Berkat jawaban sebelumnya 1 , 2 , dan sumber daya .


0

semua ini bekerja dengan bilah navigasi sederhana, tetapi bagaimana dengan sub-menu tarik-turun? ketika sub-menu dipilih, item menu teratas harus dibuat 'terkini' dalam hal ini tab_on_rails saya menjadi solusinya


0

Ini adalah bagaimana saya menyelesaikan proyek saya saat ini.

def class_if_current_page(current_page = {}, *my_class)
    if current_page?(current_page)
      my_class.each do |klass|
        "#{klass} "
      end
    end
  end

Kemudian..

li = link_to company_path 
    class: %w{ class_if_current_page( { status: "pending" }, "active" ), "company" } do  
      Current Company

0

Cara saya yang mudah -

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

Terima kasih.


0

Jika Anda juga ingin mendukung hash opsi html dalam tampilan. Misalnya jika Anda ingin memanggilnya dengan id atau kelas CSS lain, Anda dapat menentukan fungsi helper seperti ini.

def nav_link_to(text, url, options = {})
  options[:class] ||= ""
  options[:class] += " active"
  options[:class].strip!
  link_to text, url, options
end

Jadi dalam tampilan, panggil helper ini dengan cara yang sama seperti Anda memanggil link_to helper

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

0

Buat metode ApplicationHelperseperti di bawah ini.

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

Sekarang gunakan dalam tampilan seperti kasus penggunaan di bawah ini.

1. Untuk semua tindakan pengontrol tertentu

<li class="<%= active('controller_name')%>">
....
</li>

2. Untuk semua tindakan banyak pengontrol (dengan dipisahkan koma)

<li class="<%= active('controller_name1,controller_name2')%>">
....
</li>

3. Untuk tindakan spesifik dari setiap pengontrol tertentu

<li class="<%= active('controller_name', 'action_name')%>">
....
</li>

4. Untuk tindakan spesifik dari banyak pengontrol (dengan dipisahkan koma)

<li class="<%= active('controller_name1,controller_name2', 'action_name')%>">
....
</li>

5. Untuk beberapa tindakan khusus dari setiap pengontrol tertentu

<li class="<%= active('controller_name', 'index, show')%>">
....
</li>

6. Untuk beberapa tindakan tertentu dari banyak pengontrol (dengan dipisahkan koma)

<li class="<%= active('controller_name1,controller_name2', 'index, show')%>">
....
</li>

Semoga membantu

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.