Jak uzyskać nawigację Twitter-Bootstrap, aby wyświetlić aktywny link?


106

Nie rozumiem, jak Twitter Bootstrap robi aktywne linki do nawigacji. Jeśli mam regularną nawigację taką jak ta (z linkowaniem ruby ​​na szynach):

<ul class="nav">
  <li class="active"> <a href="/link">Link</a> </li>
  <li class=""> <a href="/link">Link</a> </li>
  <li class=""> <a href="/link">Link</a> </li>        
</ul>

Jak zachować aktywność na podstawie klikniętego linku?


1
FYI: używam gem active_link_to i określam {: wrap_class =>: li}. Spowoduje to utworzenie: <li class = 'active'> ... </li>, gdy REQUEST_URI pasuje do wartości HREF ...
Justin E

Odpowiedzi:


95

Właśnie odpowiedziałem na to samo pytanie tutaj Twitter Bootstrap Pills with Rails 3.2.2

<ul class="nav">
  <li class="<%= 'active' if params[:controller] == 'controller1' %>"> <a href="/link">Link</a> </li>
  <li class="<%= 'active' if params[:controller] == 'controller2' %>"> <a href="/link">Link</a> </li>
  <li class="<%= 'active' if params[:controller] == 'controller3' %>"> <a href="/link">Link</a> </li>        
</ul>

21
Myślę, że pomysł jest tutaj poprawny, ale przejście bezpośrednio do skrótu parametrów wydaje się złym pomysłem. To samo dotyczy powtarzania w kółko tego samego kodu. Poleciłbym przynajmniej użycie current_page? metoda, aby sprawdzić bieżący kontroler / akcję, a także przenieść kod do pomocnika, aby uniknąć powtórzenia kodu.
Dustin Frazier

2
Zastanawiam się, jak mam napisać to samo w haml. Konwersja do haml nie działa dla mnie. A może gdzieś się mylę
rozgrzewka na ławce rezerwowych

14
Wdrożenie HAML%li{:class => "#{'active' if current_page?(root_path)}"}=link_to "Home", root_path
Brian

Czy istnieje elegancki sposób, aby to działało z friendly_id gem bez wykonywania żądań db?
Engin Erdogan

6
Dokumentacja Rails zaleca używanie pomocników controller_namei action_namezamiast uzyskiwać do nich dostęp z hasha params.
Alexander Suraphel

171

Możesz użyć czegoś takiego (bardzo podobnego do tego, o czym wspomniał @phil, ale trochę krócej):

<ul class="nav">
  <li class="<%= 'active' if current_page?(root_path) %>"><%= link_to "Home", root_path %></li>
  <li class="<%= 'active' if current_page?(about_path) %>"><%= link_to "About", about_path %></li>
  <li class="<%= 'active' if current_page?(contact_path) %>"><%= link_to "Contact", contact_path %></li>
</ul>

10
nie działa, jeśli masz subnavigation. Ścieżka się zmienia, ale jesteś w tej samej sekcji… ma sens?
Jakob Dam Jensen

3
tak, zgadza się, jeśli chcesz podświetlić pozycję menu bez względu na to, jaką metodę używasz w tym samym kontrolerze, możesz użyć rozwiązania @Pierre:'active' if params[:controller] == 'controller1'
yorch

Tak, to najbardziej elegancki sposób na zrobienie tego! Dzięki :)
squiter

2
Jak mogę dodać więcej ścieżek lub określoną ścieżkę, jak user_*_pathw <%= 'active' if current_page?(root_path) %>?
Ismoh,

1
Jak dodać więcej niż jedną ścieżkę, aby element menu był aktywny? Na przykład, jeśli masz kilka elementów na liście rozwijanej, które są składnikami tego samego elementu menu i chcesz, aby element menu był aktywny, gdy jesteś na którejkolwiek ze stron znajdujących się w menu rozwijanym? Daj nam znać tak szybko, jak to możliwe.
msc

47

https://github.com/twg/active_link_to

<%= active_link_to 'Users', users_path, :wrap_tag => :li %>

#=> <li class="active"><a href="https://stackoverflow.com/users">Users</a></li>


7
Kocham to. Po co przepisać koło?
lightyrs

To naprawdę powinna być droga ... Chyba że nie chcesz pociągać za sobą kolejnej zależności.
Mark G.

33

Użyłem helpera, aby zaimplementować to w stylu helperów formularzy.

W pomocniku (np. app/helpers/ApplicationHelper.rb):

def nav_bar
  content_tag(:ul, class: "nav navbar-nav") do
    yield
  end
end

def nav_link(text, path)
  options = current_page?(path) ? { class: "active" } : {}
  content_tag(:li, options) do
    link_to text, path
  end
end

Następnie w widoku (np. app/views/layouts/application.html.erb):

<%= nav_bar do %>
  <%= nav_link 'Home', root_path %>
  <%= nav_link 'Posts', posts_path %>
  <%= nav_link 'Users', users_path %>
<% end %>

W tym przykładzie (na stronie „użytkownicy”):

<ul class="nav navbar-nav">
  <li><a href="/">Home</a></li>
  <li><a href="/posts">Posts</a></li>
  <li class="active"><a href="/users">Users</a></li>
</ul>

To jest świetne! Dzięki!
Krzysztof Witczak

Podoba mi się ten pomysł, jednak dodałbym trzeci argument do funkcji nav_link o nazwie html = {}, który jest następnie przekazywany do link_to. W ten sposób możesz przekazać hash html do nav_link w taki sam sposób, w jaki normalnie używasz link_to.
Ryan Friedman

22

Użyj tego zamiast tego, aby wybrać aktywny link w nawigacji na podstawie bieżącej trasy bez kodu serwera:

    $(document).ready(function () {
        $('a[href="' + this.location.pathname + '"]').parent().addClass('active');
    });

2
Jest to najlepsze rozwiązanie, ponieważ działa również z menu rozwijanymi, a ja dołączam wiersz $('li.active').closest('.dropdown').addClass('active');do podświetlenia menu nadrzędnego.
Seralto

jak to zmienić, aby ubiegać się również o podstrony? na przykład example.com/home będzie działać. Potrzebuję linku "Strona główna", aby był aktywny również w przypadku example.com/home/page .
athultuttu

11

Odniosłem sukces, używając logiki i ( &&) w haml :

%ul.nav
  %li{class: current_page?(events_path) && 'active'}
    = link_to "Events", events_path
  %li{class: current_page?(about_path) && 'active'}
    = link_to "About Us", about_path

5

Dla każdego linku:

<% if current_page?(home_path) -%><li class="active"><% else -%><li><% end -%>
  <%= link_to 'Home', home_path %>
</li>

lub nawet

<li <% if current_page?(home_path) -%>class="active"<% end -%>>
  <%= link_to 'Home', home_path %>
</li>


3

Dzisiaj miałem to samo pytanie / problem, ale z innym podejściem do rozwiązania. Tworzę funkcję pomocniczą w application_helper.rb:

def navMainAktiv(actionName)
    if params[:action] == actionName    
    "active"
    end
end

a link wygląda tak:

<li class="<%= navMainAktiv('about')%>"><%= link_to "About", about_path %></li>

Można wymienić params[:action]z params[:controller]i ustawić nazwę kontrolera w linku.


2

Używam tego dla każdego li:

<li><%= link_to_unless_current('Home', root_path) { link_to('Home', root_path, class: 'active') } %></li>


Klasa musi być ustawiona na liniea
Christopher Oezbek

2

Możesz zdefiniować metodę pomocniczą w application_helper.rb

def create_link(text, path)
  class_name = current_page?(path) ? 'active' : ''

  content_tag(:li, class: class_name) do
    link_to text, path
  end
end

Teraz możesz użyć:

create_link 'xyz', any_path który renderowałby się jako

<li class="active">
  <a href="/any">xyz</a>
</li>

Mam nadzieję, że to pomoże!


1

Powinieneś to zrobić samodzielnie, manipulując klasami CSS. Oznacza to, że jeśli użytkownik kliknie łącze, zrób coś (działanie docelowe), ustaw poprzedni link jako nieaktywny, a nowy jako aktywny.

Jeśli twoje łącza prowadzą do serwera (to znaczy przeładowują stronę), możesz po prostu poprawnie renderować aktywne łącze na serwerze. W przeciwnym razie, jeśli robisz coś po stronie klienta (przełączanie paneli kart lub cokolwiek innego), musisz użyć javascript.



1

Napisałem prostą metodę pomocnika przy użyciu pomocnika wbudowanego w widoku, current_page?kiedy można określić niestandardową classnazwę w html_optionshashu.

def active_link_to(name = nil, options = nil, html_options = nil, &block)
  active_class = html_options[:active] || "active"
  html_options.delete(:active)
  html_options[:class] = "#{html_options[:class]} #{active_class}" if current_page?(options)
  link_to(name, options, html_options, &block)
end

Przykłady (gdy jesteś na root_pathtrasie):

<%= active_link_to "Main", root_path %>
# <a href="/" class="active">Main</a>

<%= active_link_to "Main", root_path, class: "bordered" %>
# <a href="/" class="bordered active">Main</a>

<%= active_link_to "Main", root_path, class: "bordered", active: "disabled" %>
# <a href="/" class="bordered disabled">Main</a>

1

Wiele odpowiedzi tutaj zawiera rzeczy, które będą działać lub odpowiedzi częściowe. Połączyłem kilka rzeczy, aby stworzyć tę pomocniczą metodę railsów, której używam:

# helper to make bootstrap3 nav-pill <li>'s with links in them, that have
# proper 'active' class if active. 
#
# the current pill will have 'active' tag on the <li>
#
# html_options param will apply to <li>, not <a>. 
#
# can pass block which will be given to `link_to` as normal. 
def bootstrap_pill_link_to(label, link_params, html_options = {})
  current = current_page?(link_params)

  if current
    html_options[:class] ||= ""
    html_options[:class] << " active "
  end

  content_tag(:li, html_options) do
    link_to(label, link_params)
  end      
end

Można to uczynić jeszcze bardziej wyszukanym dzięki sprawdzaniu argumentów w celu obsługi &blocklinku_to itp.


1

Wiele odpowiedzi już jest, ale oto co napisałem, aby ikony Bootstrap działały z aktywnym linkiem. Mam nadzieję, że to komuś pomoże

Ten pomocnik da ci:

  1. element li z linkiem zawierającym niestandardowy tekst
  2. Opcjonalna ikona Bootstrap3
  3. uaktywni się, gdy znajdziesz się na właściwej stronie

Umieść to w swoim pliku application_helper.rb

def nav_link(link_text, link_path, icon='')
  class_name = current_page?(link_path) ? 'active' : ''
  icon_class = "glyphicon glyphicon-" + icon

  content_tag(:li, :class => class_name) do
    (class_name == '') ? (link_to content_tag(:span, " "+link_text, class: icon_class), link_path)
    : (link_to content_tag(:span, " "+link_text, class: icon_class), '#')
  end
end

I użyj linku:

<%= nav_link 'Home', root_path, 'home'  %>

Ostatni argument jest opcjonalny - doda ikonę do linku. Użyj nazw ikon glifów. Jeśli chcesz ikonę bez tekstu:

    <%= nav_link '', root_path, 'home'  %>

1

Podstawowy, bez pomocnika

<%= content_tag(:li, class: ('active' if request.path == '/contact')) do %>
    <%= link_to 'Contact', '/contact' %>
<% end %>

Używam tego, ponieważ mam więcej niż jedną klasę -

<%= content_tag(:li, class: (request.path == '/contact' ? 'active black' : 'black')) do %>
    <%= link_to 'Contact', '/contact' %>
<% end %>

1
To zadziała również dla każdej nawigacji podrzędnej ... po prostu użyj ścieżki żądania nadrzędnego w łączu podrzędnym.
scottkekoa

1

Oto co zrobiłem:

Utworzyłem ViewsHelper i zawarłem w ApplicationController:

include ViewsHelper

Inside ViewsHelper stworzyłem prostą metodę, taką jak ta:

def page_state(path)
  current_page?(path) ? 'active' : ''
end

Moim zdaniem robię to:

<li class="<%= page_state(foobar_path) %>"><%= link_to 'Foobars', foobar_path %></li>

0

Brzmisz, jakbyś potrzebował wdrożyć system nawigacji. Jeśli jest złożony, może stać się dość brzydki i dość szybki.

W takim przypadku możesz chcieć użyć wtyczki, która sobie z tym poradzi. Możesz użyć nawigacji navigasmic lub prostej (polecam navigasmic, ponieważ utrzymuje główną warstwę w widoku, gdzie należy, a nie w jakiejś konfiguracji)


0

Najkrótszy kod 

Dotyczy to ZARÓWNO elementów nawigacyjnych, jak i podrzędnych list nawigacyjnych. Możesz przekazać tablicę jedną ścieżką i poradzi sobie z obydwoma.

application_helper

# Active page method
def ap(p:);'active' if p.class == Array ? p.map{|m| current_page? m}.any? : (current_page? p) end

widok (html.erb)

<ul class="nav navbar-nav">
  <li class="<%= ap p: home_path %>">Home</li>
  <li class="<%= ap p: account_path %>">Account</li>

  <li class="dropdown <%= ap p: [users_path, new_user_path] %>">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Users</a>
    <ul class="dropdown-menu" role="menu">
      <li class="<%= ap p: users_path %>">Users</li>
      <li class="<%= ap p: new_user_path %>">Add user</li>
    </ul>
  </li>
</ul>

0

Używanie Ruby na Sinatrze ..

Używam gołego motywu bootstrap, oto przykładowy kod paska nawigacyjnego. Zwróć uwagę na nazwę klasy elementu -> .nav - tak jak jest to określane w skrypcie java.

/ Collect the nav links, forms, and other content for toggling
    #bs-example-navbar-collapse-1.collapse.navbar-collapse
      %ul.nav.navbar-nav
        %li
          %a{:href => "/demo/one"} Page One
        %li
          %a{:href => "/demo/two"} Page Two
        %li
          %a{:href => "/demo/three"} Page Three

na stronie widoku (lub częściowo) dodaj to: javascript, to musi być wykonywane za każdym razem, gdy strona się ładuje.

fragment widoku haml ->

- content_for :javascript do
  :javascript
      $(function () {
          $.each($('.nav').find('li'), function() {
              $(this).toggleClass('active',
                  $(this).find('a').attr('href') == window.location.pathname);
          });
      });

W debugerze javascript upewnij się, że wartość atrybutu „href” odpowiada parametrowi window.location.pathname. Jest to nieco inne rozwiązanie niż rozwiązanie @Zitrax, które pomogło mi naprawić mój problem.


0
  def active_navigation?(controllers_name, actions_name)
   'active' if controllers_name.include?(controller_name) && actions_name.include?(action_name)
  end

szczupły

li class=(active_navigation?(['events'], ['index', 'show'])) = link_to t('navbar.events'), events_path
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.