How to get Twitter-Bootstrap navigation to show active link?
Ruby on-RailsTwitter BootstrapRuby on-Rails Problem Overview
I'm not understanding how Twitter Bootstrap does active links for the navigation. If I have a regular navigation like this (with ruby on rails linking):
<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>
How do I keep it active based on the link clicked?
Ruby on-Rails Solutions
Solution 1 - Ruby on-Rails
You can use something like (very similar to what @phil mentioned, but a little shorter):
<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>
Solution 2 - Ruby on-Rails
Just made an answer on the very same question here https://stackoverflow.com/questions/9862524/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>
Solution 3 - Ruby on-Rails
https://github.com/twg/active_link_to
<%= active_link_to 'Users', users_path, :wrap_tag => :li %>
#=> <li class="active"><a href="/users">Users</a></li>
Solution 4 - Ruby on-Rails
I used a helper to implement this in the style of Rails' form helpers.
In a helper (e.g. 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
Then, in a view (e.g. 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 %>
This example produces (when on the 'users' page):
<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>
Solution 5 - Ruby on-Rails
Use this instead to select active link in nav based on the current route without server code:
$(document).ready(function () {
$('a[href="' + this.location.pathname + '"]').parent().addClass('active');
});
Solution 6 - Ruby on-Rails
I've found success using the logical and (&&
) in 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
Solution 7 - Ruby on-Rails
For each link:
<% if current_page?(home_path) -%><li class="active"><% else -%><li><% end -%>
<%= link_to 'Home', home_path %>
</li>
or even
<li <% if current_page?(home_path) -%>class="active"<% end -%>>
<%= link_to 'Home', home_path %>
</li>
Solution 8 - Ruby on-Rails
not sure if you are asking about how the twitter bootstrap css is used, or the rails side. I'm assuming the rails side.
if so checkout the #link_to_if
method
or the #link_to_unless_current
method
Solution 9 - Ruby on-Rails
Today I had the same question/problem but with an other approach for the solution. I create a helper function in application_helper.rb:
def navMainAktiv(actionName)
if params[:action] == actionName
"active"
end
end
and the link looks like this:
<li class="<%= navMainAktiv('about')%>"><%= link_to "About", about_path %></li>
You can replace params[:action]
with params[:controller]
and set your controller name in the link.
Solution 10 - Ruby on-Rails
Basic, No Helper
<%= content_tag(:li, class: ('active' if request.path == '/contact')) do %>
<%= link_to 'Contact', '/contact' %>
<% end %>
I use this since I have more than one class -
<%= content_tag(:li, class: (request.path == '/contact' ? 'active black' : 'black')) do %>
<%= link_to 'Contact', '/contact' %>
<% end %>
Solution 11 - Ruby on-Rails
I use this for each li
:
<li><%= link_to_unless_current('Home', root_path) { link_to('Home', root_path, class: 'active') } %></li>
Solution 12 - Ruby on-Rails
You may define a helper method in 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
Now you can use like:
create_link 'xyz', any_path
which would render as
<li class="active">
<a href="/any">xyz</a>
</li>
Hope it helps!
Solution 13 - Ruby on-Rails
You should do it yourself by manipulating CSS classes. That is, if a user clicks on some link, then do something (target action), set previous link inactive and new link active.
If your links take you to the server (that is, make page reload), then you can just render active link correctly on the server. Otherwise, if you're doing some client-side stuff (switching tab panes or whatever), you have to use javascript.
Solution 14 - Ruby on-Rails
you could use tabulous for the links
article here on how to combine tabulous with twitter bootstrap and rails 3.x
Solution 15 - Ruby on-Rails
I wrote simple helper method using build in view helper current_page?
when you can specify custom class
name in html_options
hash.
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
Examples (when you are on root_path
route):
<%= 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>
Solution 16 - Ruby on-Rails
Many of the answers here have things that will work, or partial answers. I combined a bunch of things to make this rails helper method I use:
# 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
It could be made even fancier with argument checking to support &block
on the link_to etc.
Solution 17 - Ruby on-Rails
Many answers already, but here is what I wrote to get Bootstrap Icons working with active link. Hope It will help someone
This helper will give you:
- li element with link containing custom text
- Optional Bootstrap3 Icon
- will turn active when you're on the right page
Put this in your 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
And use link:
<%= nav_link 'Home', root_path, 'home' %>
Last argument is optional - it will add icon to the link. Use names of glyph icons. If you want icon with no text:
<%= nav_link '', root_path, 'home' %>
Solution 18 - Ruby on-Rails
Here's what I did:
I created a ViewsHelper and included in ApplicationController:
include ViewsHelper
Inside ViewsHelper I created a simple method like this:
def page_state(path)
current_page?(path) ? 'active' : ''
end
In my view I do this:
<li class="<%= page_state(foobar_path) %>"><%= link_to 'Foobars', foobar_path %></li>
Solution 19 - Ruby on-Rails
You sound like you need to implement a navigation system. If it's complex, it might get pretty ugly and pretty fast.
In this case, you might want to use a plugin that can handle that. You could use navigasmic or simple navigation (I would recommend navigasmic because it keeps the main layer in a view, where it belongs, and not in some configuration)
Solution 20 - Ruby on-Rails
Shortest codeĀ
This deals with BOTH nav, and sub nav list elements. You can pass either an array a single path and will deal with both.
application_helper
# Active page method
def ap(p:);'active' if p.class == Array ? p.map{|m| current_page? m}.any? : (current_page? p) end
view (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>
Solution 21 - Ruby on-Rails
Using ruby on Sinatra ..
I m using bootstrap bare theme, here is the sample navbar code. Note the class name of the element -> .nav - as this is referred in 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
in the view page (or partial) add this :javascript, this needs to be executed every time page loads.
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);
});
});
In the javascript debugger make sure you have value of 'href' attribute matches with window.location.pathname. This is slightly different than the solution by @Zitrax which helped me fixing my issue.
Solution 22 - Ruby on-Rails
def active_navigation?(controllers_name, actions_name)
'active' if controllers_name.include?(controller_name) && actions_name.include?(action_name)
end
slim
li class=(active_navigation?(['events'], ['index', 'show'])) = link_to t('navbar.events'), events_path
Solution 23 - Ruby on-Rails
This worked for me:
<li class="nav-item <%= 'active' if current_page?(root_path) %>" >
<%= link_to 'Home', root_path, class:"nav-link"%>
</li>
<li class="nav-item <%= 'active' if current_page?(tools_path) %>" >
<%= link_to 'Tools', tools_path, class:"nav-link" %>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Request a new tool</a>
</li>
<li class="nav-item <%= 'active' if current_page?(home_about_path) %>" >
<%= link_to 'About us', home_about_path, class:"nav-link"%>
</li>
The code inside the <%= %>
is just ruby
, and the =
means that the result of that code will be displayed on the HTML.Do this for every option you want to add in your navbar and it should work fine.