Come ottenere la navigazione Twitter-Bootstrap per mostrare il collegamento attivo?


106

Non capisco come Twitter Bootstrap faccia collegamenti attivi per la navigazione. Se ho una navigazione regolare come questa (con collegamento a ruby ​​on rails):

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

Come mantenerlo attivo in base al collegamento cliccato?


1
FYI: io uso active_link_to gem e specifico {: wrap_class =>: li}. Questo creerà: <li class = 'active'> ... </li> quando REQUEST_URI corrisponde al valore HREF ...
Justin E

Risposte:


95

Ho appena risposto alla stessa domanda qui 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
Penso che l'idea sia corretta qui, ma andare direttamente all'hash params sembra una cattiva idea. Allo stesso modo per ripetere lo stesso codice più e più volte. Consiglierei almeno di usare current_page? metodo per controllare il controller / azione corrente e sposterebbe anche il codice in un helper per evitare la ripetizione del codice.
Dustin Frazier

2
Mi chiedo come faccio a scrivere lo stesso in haml. La conversione in haml non funziona per me. O forse mi sbaglio da qualche parte
scaldamani il

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

Esiste un modo elegante per far funzionare questo lavoro con friendly_id gem senza eseguire richieste db?
Engin Erdogan

6
Rails docs raccomanda l'uso di controller_namee action_namehelper invece di accedervi dall'hash params.
Alexander Suraphel

171

Puoi usare qualcosa del tipo (molto simile a quello menzionato da @phil, ma un po 'più breve):

<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
non funziona se hai la navigazione secondaria. Il percorso cambia ma tu sei nella stessa sezione .. ha senso?
Jakob Dam Jensen

3
sì, esatto, se vuoi evidenziare una voce di menu indipendentemente dal metodo che stai eseguendo all'interno dello stesso controller, puoi usare la soluzione @Pierre:'active' if params[:controller] == 'controller1'
yorch

Sì, questo è il modo più elegante per farlo! Grazie :)
squiter

2
Come posso aggiungere più percorsi o un percorso specifico come user_*_pathin <%= 'active' if current_page?(root_path) %>?
Ismoh

1
Come aggiungeresti più di un percorso per rendere attiva la voce di menu? Ad esempio, se hai più elementi in un menu a discesa che sono componenti della stessa voce di menu e desideri rendere attiva la voce di menu quando ti trovi in ​​una delle pagine trovate nel menu a discesa? Fatecelo sapere il prima possibile.
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
Lo adoro. Perché riscrivere la ruota?
lightyrs

Questa dovrebbe essere davvero la strada da percorrere ... A meno che tu non voglia creare un'altra dipendenza.
Mark G.

33

Ho usato un helper per implementarlo nello stile dei form helper di Rails.

In un aiutante (ad esempio 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

Quindi, in una vista (ad esempio 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 %>

Questo esempio produce (nella pagina "utenti"):

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

È fantastico! Grazie!
Krzysztof Witczak

Mi piace questa idea, tuttavia aggiungerei un terzo argomento alla funzione nav_link chiamato html = {} che viene poi passato a link_to. In questo modo puoi passare un hash html a nav_link nello stesso modo in cui useresti link_to normalmente.
Ryan Friedman

22

Utilizzare questo invece per selezionare il collegamento attivo nella navigazione in base al percorso corrente senza codice server:

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

2
Questa è la soluzione migliore perché funziona anche con i menu a discesa e includo anche la riga $('li.active').closest('.dropdown').addClass('active');per evidenziare il menu principale.
Seralto

come cambiarlo per richiedere anche sottopagine? come example.com/home funzionerà. Ho bisogno che il link "Home" sia attivo anche in caso di example.com/home/page .
athultuttu

11

Ho trovato successo usando il logico e ( &&) in 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

Per ogni collegamento:

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

o anche

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


3

Oggi ho avuto la stessa domanda / problema ma con un altro approccio per la soluzione. Creo una funzione di supporto in application_helper.rb:

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

e il collegamento ha questo aspetto:

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

È possibile sostituire params[:action]con params[:controller]e impostare il nome del controller nel link.


2

Lo uso per ciascuno li:

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


La classe deve essere impostata per linona
Christopher Oezbek

2

Puoi definire un metodo di supporto in 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

Ora puoi usare come:

create_link 'xyz', any_path che renderebbe come

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

Spero che sia d'aiuto!


1

Dovresti farlo da solo manipolando le classi CSS. Cioè, se un utente fa clic su un collegamento, allora fa qualcosa (azione di destinazione), imposta il collegamento precedente inattivo e il nuovo collegamento attivo.

Se i tuoi link ti portano al server (cioè fai ricaricare la pagina), allora puoi semplicemente rendere il link attivo correttamente sul server. Altrimenti, se stai facendo alcune cose sul lato client (cambiare i pannelli delle schede o altro), devi usare javascript.



1

Ho scritto un semplice metodo di supporto usando build in view helper current_page?quando puoi specificare un classnome personalizzato in html_optionshash.

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

Esempi (quando sei in root_pathviaggio):

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

Molte delle risposte qui hanno cose che funzioneranno, o risposte parziali. Ho combinato un sacco di cose per creare questo metodo di supporto per binari che uso:

# 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

Potrebbe essere reso ancora più elaborato con il controllo degli argomenti per supportare &blockil link_to ecc.


1

Molte risposte già, ma ecco cosa ho scritto per far funzionare Bootstrap Icons con collegamento attivo. Spero che possa aiutare qualcuno

Questo aiutante ti darà:

  1. elemento li con link contenente testo personalizzato
  2. Icona Bootstrap3 opzionale
  3. diventerà attivo quando sarai sulla pagina giusta

Mettilo nel tuo 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

E usa il link:

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

L'ultimo argomento è facoltativo: aggiungerà un'icona al collegamento. Usa i nomi delle icone dei glifi. Se vuoi un'icona senza testo:

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

1

Ecco cosa ho fatto:

Ho creato un ViewsHelper e incluso in ApplicationController:

include ViewsHelper

All'interno di ViewsHelper ho creato un metodo semplice come questo:

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

A mio avviso lo faccio:

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

0

Sembra che tu abbia bisogno di implementare un sistema di navigazione. Se è complesso, potrebbe diventare piuttosto brutto e abbastanza veloce.

In questo caso, potresti voler utilizzare un plugin in grado di gestirlo. Puoi usare navigasmic o navigazione semplice (consiglierei navigasmic perché mantiene il livello principale in una vista, a cui appartiene, e non in qualche configurazione)


0

Codice più breve 

Questo riguarda ENTRAMBI gli elementi dell'elenco di navigazione e di navigazione secondaria. Puoi passare a un array un singolo percorso e ti occuperai di entrambi.

application_helper

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

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

Usare il rubino su Sinatra ..

Sto usando il tema bootstrap bare, ecco il codice navbar di esempio. Notare il nome della classe dell'elemento -> .nav - poiché viene indicato nello script 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

nella pagina di visualizzazione (o parziale) aggiungi questo: javascript, deve essere eseguito ogni volta che la pagina viene caricata.

snippet di visualizzazione haml ->

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

Nel debugger javascript assicurati che il valore dell'attributo "href" corrisponda a window.location.pathname. Questo è leggermente diverso dalla soluzione di @Zitrax che mi ha aiutato a risolvere il mio problema.


0

Di base, nessun aiuto

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

Lo uso poiché ho più di una classe -

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

1
Funzionerà anche per qualsiasi navigazione secondaria ... basta usare il percorso della richiesta principale nel collegamento secondario.
scottkekoa

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

sottile

li class=(active_navigation?(['events'], ['index', 'show'])) = link_to t('navbar.events'), events_path
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.