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.