Como obter a navegação do Twitter-Bootstrap para mostrar o link ativo?


106

Não estou entendendo como o Twitter Bootstrap ativa links para a navegação. Se eu tiver uma navegação regular como esta (com link 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>

Como faço para mantê-lo ativo com base no link clicado?


1
Para sua informação: Eu uso a gem active_link_to e especifico {: wrap_class =>: li}. Isso criará: <li class = 'active'> ... </li> quando REQUEST_URI corresponder ao valor HREF ...
— Justin E

Respostas:


95

Acabei de responder a mesma pergunta aqui 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
Acho que a ideia está correta aqui, mas ir diretamente para o hash params parece uma má ideia. Da mesma forma, para repetir o mesmo código indefinidamente. Eu recomendaria pelo menos usar o current_page? para verificar o controlador / ação atual, e também moveria o código para um auxiliar para evitar a repetição do código.
— Dustin Frazier

2
Eu me pergunto como faço para escrever o mesmo no haml. Converter para haml não funciona para mim. Ou talvez eu esteja errado em algum lugar
— benchwarmer

14
Implementação de HAML%li{:class => "#{'active' if current_page?(root_path)}"}=link_to "Home", root_path
— Brian

Existe uma maneira elegante de fazer isso funcionar com a gem friendly_id sem fazer solicitações de banco de dados?
— Engin Erdogan,

6
A documentação do Rails recomenda o uso de controller_namee action_namehelpers ao invés de acessá-los a partir do hash params.
— Alexander Suraphel

171

Você pode usar algo como (muito semelhante ao que @phil mencionou, mas um pouco mais curto):

<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
não funciona se você tiver subnavegação. O caminho muda, mas você está na mesma seção .. faz sentido?
— Jakob Dam Jensen

3
sim, correto, se você quiser destacar um item de menu, não importa qual método você está executando dentro do mesmo controlador, você pode usar a solução @Pierre:'active' if params[:controller] == 'controller1'
— yorch

Sim, essa é a maneira mais elegante de fazer isso! Obrigado :)
— squiter

2
Como posso adicionar mais caminhos ou um caminho específico como user_*_pathem <%= 'active' if current_page?(root_path) %>?
— Ismoh

1
Como você adicionaria mais de um caminho para tornar o item de menu ativo? Por exemplo, se você tiver vários itens em uma lista suspensa que são componentes do mesmo item de menu e gostaria de tornar o item de menu ativo quando estiver em qualquer uma das páginas encontradas no menu suspenso? Informe-nos o mais rápido possível.
— 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
Adoro. Por que reescrever a roda?
— lightyrs

Esse realmente deve ser o caminho a seguir ... A menos que você não queira puxar outra dependência.
— Mark G.

33

Eu usei um helper para implementar isso no estilo dos helpers de formulário do Rails.

Em um ajudante (por exemplo 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

Então, em uma vista (por exemplo 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 %>

Este exemplo produz (quando na página 'usuários'):

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

Isso é ótimo! Obrigado!
— Krzysztof Witczak

Gosto dessa ideia, mas adicionaria um terceiro argumento à função nav_link chamado html = {} que é então passado para link_to. Dessa forma, você pode passar um hash html para nav_link da mesma forma que usaria link_to normalmente.
— Ryan Friedman

22

Em vez disso, use para selecionar o link ativo no nav com base na rota atual sem o código do servidor:

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

2
Esta é a melhor solução porque também funciona com menus suspensos e incluo a linha $('li.active').closest('.dropdown').addClass('active');para destacar o menu principal também.
— Seralto

como alterá-lo para se inscrever em subpáginas também? como example.com/home funcionará. Preciso que o link "Home" esteja ativo no caso de example.com/home/page também.
— athultuttu

11

Tive sucesso usando o lógico e ( &&) em 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

Para cada link:

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

ou mesmo

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


3

Hoje tive a mesma dúvida / problema mas com outra abordagem para a solução. Eu crio uma função auxiliar em application_helper.rb:

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

e o link se parece com este:

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

Você pode substituir params[:action]com params[:controller]e definir o nome do controlador no link.


2

Eu uso isso para cada um li:

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


A aula precisa ser definida para linãoa
— Christopher Oezbek

2

Você pode definir um método auxiliar em 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

Agora você pode usar como:

create_link 'xyz', any_path que renderizaria como

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

Espero que ajude!


1

Você deve fazer isso manipulando classes CSS. Ou seja, se um usuário clicar em algum link, então faça algo (ação de destino), defina o link anterior inativo e o novo link ativo.

Se seus links o levarem ao servidor (ou seja, fazer a página recarregar), você poderá apenas renderizar o link ativo corretamente no servidor. Caso contrário, se você estiver fazendo alguma coisa do lado do cliente (alternando painéis de guia ou qualquer outra coisa), você terá que usar javascript.



1

Eu escrevi um método auxiliar simples usando build in view helper current_page?quando você pode especificar o classnome personalizado em 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

Exemplos (quando você está na root_pathrota):

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

Muitas das respostas aqui têm coisas que funcionam, ou respostas parciais. Combinei um monte de coisas para fazer este método auxiliar do Rails que 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

Pode ser ainda mais elaborado com a verificação de argumentos para suporte &blockno link_to etc.


1

Muitas respostas já, mas aqui está o que escrevi para fazer os ícones do Bootstrap funcionarem com o link ativo. Espero que ajude alguém

Este ajudante lhe dará:

  1. elemento li com link contendo texto personalizado
  2. Ícone Opcional Bootstrap3
  3. ficará ativo quando você estiver na página certa

Coloque isso em seu 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 use o link:

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

O último argumento é opcional - ele adicionará um ícone ao link. Use nomes de ícones de glifo. Se você quiser um ícone sem texto:

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

1

Aqui está o que eu fiz:

Eu criei um ViewsHelper e incluí no ApplicationController:

include ViewsHelper

Dentro do ViewsHelper, criei um método simples como este:

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

Na minha opinião, eu faço o seguinte:

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

0

Parece que você precisa implementar um sistema de navegação. Se for complexo, pode ficar muito feio e muito rápido.

Nesse caso, você pode querer usar um plugin que possa lidar com isso. Você pode usar navigasmic ou navegação simples (eu recomendo navigasmic porque mantém a camada principal em uma visualização, onde ela pertence, e não em alguma configuração)


0

Código mais curto 

Isso lida com AMBOS os elementos da lista de nav e sub nav. Você pode passar uma matriz por um único caminho e lidará com ambos.

application_helper

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

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

Usando rubi no Sinatra ..

Estou usando o tema básico de bootstrap, aqui está o código de navbar de exemplo. Observe o nome da classe do elemento -> .nav - como é referido no java script.

/ 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 página de visualização (ou parcial) adicione: javascript, isso precisa ser executado toda vez que a página carrega.

haml view snippet ->

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

No depurador javascript, certifique-se de que o valor do atributo 'href' corresponda a window.location.pathname. Isso é um pouco diferente da solução da @Zitrax, que me ajudou a corrigir meu problema.


0

Básico, sem auxiliar

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

Eu uso isso porque tenho mais de uma aula -

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

1
Isso também funcionará para qualquer subnavegação ... basta usar o caminho da solicitação pai no sublink.
— scottkekoa

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

fino

li class=(active_navigation?(['events'], ['index', 'show'])) = link_to t('navbar.events'), events_path
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.