Comment faire en sorte que la navigation Twitter-Bootstrap affiche le lien actif?

106

Je ne comprends pas comment Twitter Bootstrap crée des liens actifs pour la navigation. Si j'ai une navigation régulière comme celle-ci (avec liaison rubis sur 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>

Comment le garder actif en fonction du lien sur lequel j'ai cliqué?

LearningRoR
la source
1
FYI: J'utilise le gem active_link_to et spécifie {: wrap_class =>: li}. Cela créera: <li class = 'active'> ... </li> lorsque REQUEST_URI correspond à la valeur HREF ...
Justin E

Réponses:

95

Je viens de répondre à la même question ici 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>
Pierre
la source
21
Je pense que l'idée est correcte ici, mais aller directement au hachage des paramètres semble être une mauvaise idée. De même pour répéter le même code encore et encore. Je recommanderais au moins d'utiliser la page_actuelle? méthode pour vérifier le contrôleur / action actuel, et déplacerait également le code dans un assistant pour éviter la répétition du code.
Dustin Frazier
2
Je me demande comment j'écris la même chose en haml. La conversion en haml ne fonctionne pas pour moi. Ou peut-être que je me trompe quelque part
benchwarmer
14
Implémentation HAML%li{:class => "#{'active' if current_page?(root_path)}"}=link_to "Home", root_path
Brian
Existe-t-il un moyen élégant de faire fonctionner cela avec le gem friendly_id sans faire de requêtes de base de données?
Engin Erdogan
6
La documentation Rails recommande l'utilisation de controller_nameet des action_namehelpers au lieu d'y accéder à partir du hachage des paramètres.
Alexander Suraphel le
171

Vous pouvez utiliser quelque chose comme (très similaire à ce que @phil a mentionné, mais un peu plus court):

<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>
yorch
la source
10
ne fonctionne pas si vous avez sous-navigation. Le chemin change mais vous êtes dans la même section .. ça a du sens?
Jakob Dam Jensen
3
oui, correct, si vous souhaitez mettre en surbrillance un élément de menu quelle que soit la méthode que vous utilisez dans le même contrôleur, vous pouvez utiliser la solution @Pierre:'active' if params[:controller] == 'controller1'
yorch
Oui, c'est la manière la plus élégante de le faire! Merci :)
squiter
2
Comment puis-je ajouter plus de chemins ou un chemin spécifique comme user_*_pathdans <%= 'active' if current_page?(root_path) %>?
Ismoh
1
Comment ajouteriez-vous plus d'un chemin pour rendre l'élément de menu actif? Par exemple, si vous avez plusieurs éléments dans une liste déroulante qui sont des composants du même élément de menu et que vous souhaitez rendre l'élément de menu actif lorsque vous êtes sur l'une des pages du menu déroulant? Veuillez nous le faire savoir dès que possible.
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>

Hesham
la source
7
Aimer. Pourquoi réécrire la roue?
lightyrs
Cela devrait vraiment être la voie à suivre ... À moins que vous ne vouliez pas créer une autre dépendance.
Mark G.
33

J'ai utilisé un assistant pour implémenter cela dans le style des aides de formulaire de Rails.

Dans un assistant (par exemple 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

Ensuite, dans une vue (par exemple 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 %>

Cet exemple produit (sur la page 'utilisateurs'):

<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>
Daniel
la source
C'est bien! Merci!
Krzysztof Witczak
J'aime cette idée, mais j'ajouterais un troisième argument à la fonction nav_link appelée html = {} qui est ensuite passée à link_to. De cette façon, vous pouvez passer un hachage html à nav_link de la même manière que vous utiliseriez normalement link_to.
Ryan Friedman le
22

Utilisez plutôt ceci pour sélectionner le lien actif dans la navigation en fonction de l'itinéraire actuel sans code serveur:

    $(document).ready(function () {
        $('a[href="' + this.location.pathname + '"]').parent().addClass('active');
    });
Christian Landgren
la source
2
C'est la meilleure solution car elle fonctionne également avec les menus déroulants, et j'inclus la ligne $('li.active').closest('.dropdown').addClass('active');pour mettre en évidence le menu parent également.
Seralto
comment le changer pour s'appliquer également aux sous-pages? comme example.com/home fonctionnera. J'ai besoin du lien "Accueil" pour être actif dans le cas de example.com/home/page également.
athultuttu
11

J'ai trouvé le succès en utilisant le logique et ( &&) dans 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
Meltemi
la source
5

Pour chaque lien:

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

ou même

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

Je ne sais pas si vous demandez comment le css de bootstrap Twitter est utilisé, ou le côté des rails. Je suppose du côté des rails.

si c'est le cas, vérifiez la #link_to_ifméthode ou la #link_to_unless_currentméthode

cpjolicoeur
la source
3

Aujourd'hui, j'ai eu la même question / problème mais avec une autre approche pour la solution. Je crée une fonction d'assistance dans application_helper.rb:

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

et le lien ressemble à ceci:

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

Vous pouvez remplacer params[:action]avec params[:controller]et configurer votre nom de contrôleur dans le lien.

la force
la source
2

J'utilise ceci pour chacun li:

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

andreofthecape
la source
La classe doit être définie pour linona
Christopher Oezbek
2

Vous pouvez définir une méthode d'assistance dans 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

Maintenant, vous pouvez utiliser comme:

create_link 'xyz', any_path qui rendrait comme

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

J'espère que ça aide!

Dusht
la source
1

Vous devriez le faire vous-même en manipulant les classes CSS. Autrement dit, si un utilisateur clique sur un lien, faites quelque chose (action cible), définissez le lien précédent inactif et le nouveau lien actif.

Si vos liens vous amènent au serveur (c'est-à-dire, rechargez la page), vous pouvez simplement rendre le lien actif correctement sur le serveur. Sinon, si vous faites des choses côté client (changer de volet d'onglets ou autre), vous devez utiliser javascript.

Sergio Tulentsev
la source
1

vous pouvez utiliser tabulous pour les liens

article ici sur comment combiner tabulous avec twitter bootstrap et rails 3.x

stephenmurdoch
la source
1

J'ai écrit une méthode d'assistance simple en utilisant l'assistant de construction dans la vue current_page?lorsque vous pouvez spécifier un classnom personnalisé dans le html_optionshachage.

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

Exemples (lorsque vous êtes en root_pathroute):

<%= 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>
cintrzyk
la source
1

Beaucoup de réponses ici ont des choses qui fonctionneront ou des réponses partielles. J'ai combiné un tas de choses pour créer cette méthode d'aide aux rails que j'utilise:

# 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

Cela pourrait être rendu encore plus sophistiqué avec la vérification des arguments à prendre en charge &blocksur le link_to, etc.

jrochkind
la source
1

Beaucoup de réponses déjà, mais voici ce que j'ai écrit pour que les icônes Bootstrap fonctionnent avec un lien actif. J'espère que cela aidera quelqu'un

Cet assistant vous donnera:

  1. Élément li avec lien contenant du texte personnalisé
  2. Icône Bootstrap3 en option
  3. deviendra actif lorsque vous serez sur la bonne page

Mettez ceci dans votre 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

Et utilisez le lien:

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

Le dernier argument est facultatif - il ajoutera une icône au lien. Utilisez les noms des icônes de glyphe. Si vous voulez une icône sans texte:

    <%= nav_link '', root_path, 'home'  %>
Lukasz Muzyka
la source
1

Voici ce que j'ai fait:

J'ai créé un ViewsHelper et inclus dans ApplicationController:

include ViewsHelper

Dans ViewsHelper, j'ai créé une méthode simple comme celle-ci:

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

À mon avis, je fais ceci:

<li class="<%= page_state(foobar_path) %>"><%= link_to 'Foobars', foobar_path %></li>
Nick Res
la source
0

Vous semblez devoir mettre en place un système de navigation. Si c'est complexe, cela peut devenir assez laid et assez rapide.

Dans ce cas, vous voudrez peut-être utiliser un plugin capable de gérer cela. Vous pouvez utiliser la navigation navigasmique ou simple (je recommanderais navigasmic car elle garde la couche principale dans une vue, à sa place, et non dans une configuration)

Andrei S
la source
0

Code le plus court 

Cela concerne les deux éléments de la liste de navigation et de sous-navigation. Vous pouvez transmettre à un tableau un seul chemin et traiter les deux.

application_helper

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

vue (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>
cb24
la source
0

Utilisation de ruby ​​sur Sinatra.

J'utilise le thème nu bootstrap, voici l'exemple de code de la barre de navigation. Notez le nom de classe de l'élément -> .nav - car il est référencé dans le 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

dans la page d'affichage (ou partielle), ajoutez ceci: javascript, cela doit être exécuté à chaque chargement de la page.

extrait de vue haml ->

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

Dans le débogueur javascript, assurez-vous que la valeur de l'attribut 'href' correspond à window.location.pathname. C'est légèrement différent de la solution de @Zitrax qui m'a aidé à résoudre mon problème.

Rishi
la source
0

Basique, sans aide

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

J'utilise ceci depuis que j'ai plus d'une classe -

<%= content_tag(:li, class: (request.path == '/contact' ? 'active black' : 'black')) do %>
    <%= link_to 'Contact', '/contact' %>
<% end %>
Scottkekoa
la source
1
Cela fonctionnera également pour toute sous-navigation ... utilisez simplement le chemin de la demande parent dans le sous-lien.
scottkekoa
0
  def active_navigation?(controllers_name, actions_name)
   'active' if controllers_name.include?(controller_name) && actions_name.include?(action_name)
  end

svelte

li class=(active_navigation?(['events'], ['index', 'show'])) = link_to t('navbar.events'), events_path
Nazar Hlynskyi
la source