Как сделать так, чтобы в навигации Twitter-Bootstrap отображалась активная ссылка?

106

Я не понимаю, как Twitter Bootstrap делает активные ссылки для навигации. Если у меня такая обычная навигация (с привязкой рубина на рельсах):

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

Как сохранить его в активном состоянии на основе нажатой ссылки?

LearningRoR
источник
1
К вашему сведению: я использую гем active_link_to и указываю {: wrap_class =>: li}. Это создаст: <li class = 'active'> ... </li>, когда REQUEST_URI совпадает со значением HREF ...
Джастин Э

Ответы:

95

Только что ответил на тот же вопрос здесь 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
Я думаю, что идея здесь правильная, но переход непосредственно к хешу params кажется плохой идеей. То же самое для повторения одного и того же кода снова и снова. Я бы порекомендовал хотя бы использовать current_page? для проверки текущего контроллера / действия, а также переместит код в помощник, чтобы избежать повторения кода.
Дастин Фрейзер,
2
Интересно, как в хамл написать то же самое. У меня не работает преобразование в haml. Или, может быть, я где-то ошибаюсь
Benchwarmer
14
Реализация HAML%li{:class => "#{'active' if current_page?(root_path)}"}=link_to "Home", root_path
Брайан
Есть ли элегантный способ сделать эту работу с драгоценным камнем friendly_id без запросов к базе данных?
Энгин Эрдоган
6
Рельсы документы рекомендует использовать controller_nameи action_nameпомощник вместо того , чтобы доступ к ним из хэша Params.
Александр Сурафель
171

Вы можете использовать что-то вроде (очень похоже на то, что упомянул @phil, но немного короче):

<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
не работает, если у вас есть поднавигация. Путь меняется, но вы находитесь в том же разделе .. имеет смысл?
Jakob Dam Jensen
3
да, правильно, если вы хотите выделить пункт меню, независимо от того, какой метод вы используете внутри одного контроллера, вы можете использовать решение @Pierre:'active' if params[:controller] == 'controller1'
yorch
Да, это самый элегантный способ сделать это! Спасибо :)
сквитер
2
Как я могу добавить больше путей или конкретный путь, как user_*_pathв <%= 'active' if current_page?(root_path) %>?
Ismoh
1
Как бы вы добавили более одного пути, чтобы сделать пункт меню активным? Например, если у вас есть несколько элементов в раскрывающемся списке, которые являются компонентами одного и того же элемента меню, и вы хотите, чтобы этот элемент меню был активным, когда вы находитесь на любой из страниц, найденных в раскрывающемся меню? Пожалуйста, дайте нам знать как можно скорее.
msc 07
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
источник
7
Любить это. Зачем переписывать колесо?
lightyrs
Это действительно должно быть выходом ... Если вы не хотите использовать другую зависимость.
Марк Г.
33

Я использовал помощник, чтобы реализовать это в стиле помощников форм Rails.

В помощнике (например 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

Затем в представлении (например 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 %>

Этот пример производит (когда находится на странице "пользователи"):

<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>
Даниэль
источник
Это круто! Спасибо!
Кшиштоф Витчак
Мне нравится эта идея, однако я бы добавил к функции nav_link третий аргумент, называемый html = {}, который затем передается в link_to. Таким образом, вы можете передать html-хэш в nav_link так же, как вы обычно используете link_to.
Райан Фридман
22

Используйте это вместо этого, чтобы выбрать активную ссылку в навигации на основе текущего маршрута без кода сервера:

    $(document).ready(function () {
        $('a[href="' + this.location.pathname + '"]').parent().addClass('active');
    });
Кристиан Ландгрен
источник
2
Это лучшее решение, потому что оно работает и с раскрывающимися меню, и я также включаю строку, $('li.active').closest('.dropdown').addClass('active');чтобы выделить родительское меню.
Seralto
как изменить его, чтобы также применять для подстраниц? например example.com/home будет работать. Мне нужно, чтобы ссылка «Главная» была активной и в случае example.com/home/page .
athultuttu
11

Я нашел успех, используя логическое и ( &&) в 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

Для каждой ссылки:

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

или даже

<li <% if current_page?(home_path) -%>class="active"<% end -%>>
  <%= link_to 'Home', home_path %>
</li>
Фил Пирожков
источник
3

Не уверен, спрашиваете ли вы, как используется твиттер-бутстрап css или о рельсах. Я принимаю сторону рельсов.

если да, проверьте #link_to_ifметод или #link_to_unless_currentметод

cpjolicoeur
источник
3

Сегодня у меня был тот же вопрос / проблема, но с другим подходом к решению. Я создаю вспомогательную функцию в application_helper.rb:

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

и ссылка выглядит так:

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

Вы можете заменить его params[:action]на params[:controller]и указать имя вашего контроллера в ссылке.

сила
источник
2

Я использую это для каждого li:

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

andreofthecape
источник
Класс должен быть установлен, чтобы liне былоa
Кристофер Оезбек
2

Вы можете определить вспомогательный метод в 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

Теперь вы можете использовать как:

create_link 'xyz', any_path который будет отображаться как

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

Надеюсь, поможет!

Душт
источник
1

Вы должны сделать это сами, манипулируя классами CSS. То есть, если пользователь нажимает на какую-то ссылку, затем что-то делает (целевое действие), делает предыдущую ссылку неактивной, а новую - активной.

Если по вашим ссылкам вы попадаете на сервер (то есть перезагружаете страницу), вы можете просто правильно отобразить активную ссылку на сервере. В противном случае, если вы делаете что-то на стороне клиента (переключение панелей вкладок или что-то еще), вам придется использовать javascript.

Серджио Тюленцев
источник
1

вы можете использовать tabulous для ссылок

статья здесь о том , как совместить tabulous с Twitter Bootstrap и рельсы 3.x

Стивенмердок
источник
1

Я написал простой вспомогательный метод с использованием вспомогательного метода построения в представлении, current_page?когда вы можете указать собственное classимя в html_optionsхеш-функции.

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

Примеры (когда вы в root_pathпути):

<%= 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
источник
1

Многие из ответов здесь содержат то, что будет работать, или частичные ответы. Я объединил кучу вещей, чтобы сделать этот вспомогательный метод рельсов, который я использую:

# 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

Это можно было бы сделать еще более привлекательным с помощью проверки аргументов для поддержки &blockв link_to и т. Д.

Jrochkind
источник
1

Уже много ответов, но вот что я написал, чтобы значки Bootstrap работали с активной ссылкой. Надеюсь, это поможет кому-то

Этот помощник даст вам:

  1. li элемент со ссылкой, содержащей настраиваемый текст
  2. Необязательный значок Bootstrap3
  3. станет активным, когда вы окажетесь на правой странице

Поместите это в свой 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

И используйте ссылку:

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

Последний аргумент не обязателен - он добавит иконку к ссылке. Используйте имена значков глифов. Если вам нужен значок без текста:

    <%= nav_link '', root_path, 'home'  %>
Лукаш Музыка
источник
1

Базовый, без помощника

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

Я использую это, так как у меня более одного класса -

<%= content_tag(:li, class: (request.path == '/contact' ? 'active black' : 'black')) do %>
    <%= link_to 'Contact', '/contact' %>
<% end %>
Скотткекоа
источник
1
Это также будет работать для любой суб-навигации ... просто используйте родительский путь запроса в дополнительной ссылке.
scottkekoa
1

Вот что я сделал:

Я создал ViewsHelper и включил в ApplicationController:

include ViewsHelper

Внутри ViewsHelper я создал такой простой метод:

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

На мой взгляд, я делаю так:

<li class="<%= page_state(foobar_path) %>"><%= link_to 'Foobars', foobar_path %></li>
Ник Рес
источник
0

Похоже, вам нужно внедрить систему навигации. Если это сложно, это может стать довольно уродливым и довольно быстрым.

В этом случае вы можете использовать плагин, который справится с этим. Вы можете использовать navigasmic или простую навигацию (я бы рекомендовал navigasmic, потому что он сохраняет основной уровень в представлении, которому он принадлежит, а не в какой-либо конфигурации)

Андрей С
источник
0

Самый короткий код 

Это касается как элементов списка навигации, так и суб-навигации. Вы можете передать любой массив по одному пути и работать с обоими.

application_helper

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

просмотр (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
источник
0

Использование рубина на Sinatra ..

Я использую голую тему начальной загрузки, вот пример кода навигационной панели. Обратите внимание на имя класса элемента -> .nav - как это указано в 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

на странице просмотра (или частично) добавьте это: javascript, это должно выполняться каждый раз при загрузке страницы.

фрагмент просмотра haml ->

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

В отладчике javascript убедитесь, что значение атрибута 'href' совпадает с window.location.pathname. Это немного отличается от решения @Zitrax, которое помогло мне исправить мою проблему.

Риши
источник
0
  def active_navigation?(controllers_name, actions_name)
   'active' if controllers_name.include?(controller_name) && actions_name.include?(action_name)
  end

тонкий

li class=(active_navigation?(['events'], ['index', 'show'])) = link_to t('navbar.events'), events_path
Назар Глинский
источник