Як отримати навігацію 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>

Як я можу підтримувати його активним на основі натиснутого посилання?


1
FYI: я використовую gem active_link_to і вказую {: wrap_class =>: li}. Це створить: <li class = 'active'> ... </li> коли REQUEST_URI відповідає значенню HREF ...
Justin E

Відповіді:


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
Я думаю, що ідея тут правильна, але переходити безпосередньо до хеш-парамів здається поганою ідеєю. Так само для повторення одного і того ж коду знову і знову. Я б рекомендував хоча б використовувати current_page? метод перевірки поточного контролера / дії, а також перемістить код у помічник, щоб уникнути повторення коду.
Дастін Фрейзьє

2
Цікаво, як я можу записати те саме в haml. Перетворення на HTML не працює для мене. Або, можливо, я десь помиляюся
1212

14
Впровадження HAML%li{:class => "#{'active' if current_page?(root_path)}"}=link_to "Home", root_path
Брайан

Чи є елегантний спосіб зробити цю роботу за допомогою gem friendly_id, не виконуючи запити на db?
Енґін Ердоган

6
Документи Rails рекомендують використовувати controller_nameі action_nameпомічники замість доступу до них з хеш-парамів.
Олександр Сурафель

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
не працює, якщо у вас є субнавігація. Шлях змінюється, але ви знаходитесь в тому ж розділі .. має сенс?
Якоб Дам Йенсен

3
так, правильно, якщо ви хочете виділити пункт меню незалежно від того, яким методом ви працюєте в одному контролері, ви можете використовувати рішення @Pierre:'active' if params[:controller] == 'controller1'
yorch

Так, це найелегантніший спосіб зробити це! Дякую :)
сквітер

2
Як я можу додати більше шляхів або певний шлях, як user_*_pathу <%= 'active' if current_page?(root_path) %>?
Ісмох

1
Як би ви додали більше одного шляху, щоб активувати пункт меню? Наприклад, якщо у випадаючому меню є кілька елементів, які є компонентами того ж пункту меню, і ви хочете зробити цей пункт активним, коли ви перебуваєте на будь-якій зі сторінок, що знаходяться у спадному меню? Будь ласка, повідомте нас якнайшвидше.
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
Любіть це. Навіщо переписувати колесо?
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

Використовуйте це замість цього, щоб вибрати активне посилання у nav, заснований на поточному маршруті без коду сервера:

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

2
Це найкраще рішення, оскільки воно працює і зі спадними меню, і я включаю рядок, $('li.active').closest('.dropdown').addClass('active');щоб виділити батьківське меню теж.
Сералто

як це змінити, щоб подати заявку і на підсторінки? як-от 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 twitter bootstrap або сторона рейки. Я припускаю сторону рейок.

якщо так, замовіть #link_to_ifметод чи #link_to_unless_currentметод


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

Ви можете визначити метод помічника в 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

ви можете використовувати табличні для посилань

стаття тут про те, як поєднувати табличні з завантажувальним тріптером та рейками 3.x


1

Я написав простий метод помічника, використовуючи held build в перегляді, 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>

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 тощо.


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

Ось що я зробив:

Я створив 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

Вам здається, що вам потрібно впровадити систему навігації. Якщо він складний, він може вийти досить потворним і досить швидко.

У цьому випадку ви можете використовувати плагін, який може це впоратися. Ви можете використовувати навігаційну або просту навігацію (я б рекомендував навігасмічну, оскільки він зберігає основний шар у вигляді, де він належить, а не в якійсь конфігурації)


0

Найкоротший код 

Це стосується елементів BOTH nav та sub navi list. Ви можете пропустити будь-який масив єдиним шляхом і буде мати справу з обома.

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>

0

Використання рубіну на Сінатрі ..

Я використовую відкриту тему для завантаження, ось приклад коду навбар. Зверніть увагу на назву класу елемента -> .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

Основний, без помічника

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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.