This is what I have and I want to include it in a partial so that I am not duplicating it in 4 places. The problem is the active class which should change based on the page the user is on. How can I go about this? Or am I better off just repeating the code in 4 templates?
<div class="navbox">
<ul class="nav">
Account</li>
<li> Profile</li>
<li> Photos</li>
<li> Security</li>
</ul>
</div>
Pass in an active local when rendering:
render :partial => 'navbox', :locals => { :active => 'Account' }
Then have this as your partial:
<div class="navbox">
<ul class="nav">
<a href="#"<% if active == 'Account' %> class="active"<% end %>> Account</li></a>
<a href="#"<% if active == 'Profile' %> class="active"<% end %>><li> Profile</li></a>
<a href="#"<% if active == 'Photos' %> class="active"<% end %>><li> Photos</li></a>
<a href="#"<% if active == 'Security' %> class="active"<% end %>><li> Security</li></a>
</ul>
</div>
There's various ways this could be cleaned-up (link_to, helper methods, etc.), which is left as an exercise. You could also potentially avoid needing to pass in a local if you can deduce whether something is “active” from the request URL.
Also have a look at link_to_unless_current & link_to_unless if you don't want to link at all instead of adding a class to the link.
Look for the active_link_to gem https://github.com/twg/active_link_to
It is the easiest way
You can try to crete helper like this:
{'Account' => account_path, 'Profile' => profile_path...etc}.each do |name, path|
content_tag :li do
link_to name, path, class: (current_page?(path) 'active' : 'regular')
end
end
Also take a look at method link_to_unless_current http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to_unless_current
Related
What is the best approach of dealing with class="active" problems in Rails?
I've found how to deal with this for single links, but when classes has to be set to "active" in different parts of the template, how do one deal with this?
Here is my code:
module AdminHelper
def nav_link(link_text, link_path)
class_name = current_page?(link_path) ? 'active' : nil
content_tag(:li) do
link_to link_text, link_path, :class => class_name
end
end
def active_section(section)
request.fullpath.start_with?(section)
end
end
And in the layout holding the menu:
<% if active_section('/superadmin') %>
<li class="active">
<% else %>
<li>
<% end %>
<i class="fa fa-asterisk fa-fw"></i> Superadmin <span class="fa arrow"></span>
<ul class="nav nav-second-level">
<%= nav_link 'Add Account', superadmin_new_account_path %>
<%= nav_link 'List Accounts', superadmin_list_accounts_path %>
</ul>
</li>
That is, I need to check if I am at a specific part of the url structure, and outputting the li class="active" in case of that. Otherwise just outputting the li element without class. I am using a menu; MetisMenu and needs to set this class so correct section is expanded.
My code works but it feels horrible wrong way to do it.
Would be really happy if someone can give a hint on how to do this the right way!
I recommend using simple-navigation gem
Not to be 'that guy', but have you looked into HAML? It makes doing conditional classing a ton easier. It also reads/looks much cleaner. i.e.
%li{:class => ("active" if active_section('/superadmin'))}
in the bootstrap navigation bar. You can get the effect of a button being clicked by adding the class active . Naturally, I want to use this on my pages. For example if I'm on the about us page I want the about us button clicked.
What is the best way to go about this? I was going to go to each page and at the bottom have a jQuery function add the class active to it. Is there a better way?
Read about current_page? here
You can add a method for handle logic with current_page?, example a method :
module ApplicationHelper
def active_class(link_path)
current_page?(link_path) ? "active" : ""
end
end
example bootstrap navbar template
<div class="navbar">
<div class="navbar-inner">
<a class="brand" href="#">Title</a>
<ul class="nav">
<li class="active">Home</li>
<li>Link</li>
<li>Link</li>
</ul>
</div>
</div>
So, on view looks like
HTML
<li class="<%= active_class(some_path) %>">
<%= link_to "text of link", some_path %>
</li>
HAML
%li{:class => active_class(some_path)}
= link_to "text of link", some_path
Or you can use request.fullpath to get current full of path if a current path have a parameter
example
<ul>
<% Contry.all.each do |c| %>
<li class="snavitem <%= active_class(contry_path(c)) %>">
<%= link_to "show #{c.name}", contry_path(c) %>
</li>
<% end %>
</ul>
and on your application_helper.rb
def active_class(link_path)
request.fullpath == link_path ? "active" : ""
end
read about request.fullpath here
in my opinion, a cleaner way to achieve that is to write a link_to_in_li method in application_helper.rb:
def link_to_in_li(body, url, html_options = {})
active = "active" if current_page?(url)
content_tag :li, class: active do
link_to body, url, html_options
end
end
then use it this way
<%= link_to_in_li "Home", root_path, id: "home_link" %>
I find the code inside li a little difficult to read.
For anyone having trouble making sense of this, here is an example with my paths and filenames laid out explicitly. As a pretty new person to rails, I was having trouble figuring it out. Thanks to the other people who answered above, as it helped me figure it out!
I placed the Bootstrap navbar in my application.html.erb file:
<div class="navbar-header">
<a class="navbar-brand" href="/">Mapper</a>
<ul class="nav navbar-nav">
<li class="<%= is_active?('/') %>"><%= link_to "Home", '/' %></li>
<li class="<%= is_active?('/main/map') %>"><%= link_to "Map", '/main/map' %></li>
<li class="<%= is_active?('/main/about') %>"><%= link_to "About", '/main/about' %></li>
</ul>
</div>
This goes in the application_helper.rb file:
module ApplicationHelper
def is_active?(link_path)
current_page?(link_path) ? "active" : ""
end
end
That's it! Now your application will dynamically add the 'active' class to whatever page is currently being viewed (i.e. it's corresponding list item in the navbar). This is much simpler (and more DRY) than adding the navbar manually to each page (view) and then updating the 'active' class.
I'll post my answer that I created based on these others because in case of CRUD views the active class wasn't been placed.
module ApplicationHelper
def active_class(name)
controller_name.eql?(name) || current_page?(name) ? 'active' : ''
end
end
My views use something like this:
<ul class="nav navbar-nav">
<li class="nav-item <%= active_class('/') %>">
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item <%= active_class('leads') %>">
<a class="nav-link" href="/leads">Leads</a>
</li>
</ul>
<ul class="nav navbar-nav pull-right <%= active_class(edit_user_registration_path) %>">
<li class="nav-item ">
<a class="nav-link" href="/users/edit">Perfil</a>
</li>
<li class="nav-item">
<%= link_to('Sair', destroy_user_session_path, method: :delete) %>
</li>
</ul>
Please try this in each page, check the cotroller or action and add the css
For example:
<li class= <%= (controller.controller_name.eql?('pages') && controller.action_name.eql?('index') )? 'active':''%> ><%= link_to 'my page', pages_path%></li>
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">xyz</li>
Perfect for bootstrap navigation!
Why limit yourself to only li elements? And why not support multiple class names along with active? This solution lets me:
Support not only plain text but HTML inside link_to (e.g. add an icon inside the link)
Add just few lines of code to application_helper.rb
Append active to the whole class name of the link element instead of it being the sole class.
So, add this to application_helper.rb:
def active_class?(class_name = nil, path)
class_name ||= ""
class_name += " active" if current_page?(path)
class_name.strip!
return class_name
end
And on your template you can have something like this:
<div class="col-xs-3">
<%= link_to root_path, :class => active_class?("btn btn-outline-primary", root_path) do %>
<i class="fa fa-list-alt fa-fw"></i>
<% end %>
</div>
You can also specify or not a class_name and use it like this:
<li class="<%= active_class?(root_path) %>">Home</li>
Thanks to previous answers 1, 2 and resources.
I followed the basic railscast for using Twitter Bootstrap in Rails application. Everything was great, until I had to push to heroku, then I had some problems with pg gem, and I had to rake assets:precompile to push it ok. Finally I solved.
Now, I'm trying to use pills in my application, I have copy/paste from documentation and changed the url in href :)
<div class="container">
<div class="row">
<div class="span3">
<p> Lorem Ipsum</p>
</div>
<div class="span9">
<ul class="nav nav-pills">
<li class="active">Home</li>
<li>Products</li>
<li>Categories</li>
</ul>
</div>
</div>
</div>
When I push one of the links, I'm redirected to the right url but the selected option doesn't change to class="active". I don't know why... I thought it was the javascript but hover property works ok... I mean, when the mouse is over an option (diferent from active) its style changes ok.
I tried rake assets:clean, but no change is made
Thanks
You actually have to handle this by yourself!
Your list should look something like
<li class="<%= 'active' if params[:controller] == 'yourdefaultcontroller' %>">Home</li>
<li class="<%= 'active' if params[:controller] == 'products' %>">Products</li>
<li class="<%= 'active' if params[:controller] == 'categories' %>">Categories</li>
You need to specify in each request which tab is the active one. You can do this by relying on the name of the controller (and action if need be) that is passed in the params hash.
You can use something like this:
<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>
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>Home</li>
<li>Posts</li>
<li class="active">Users</li>
</ul>
I am trying to set an li class of active based on what page the user is on.
I have 4 navigation elements and they all look something like this:
<% if #activeLi == "home" %>
<li class="active">
<% else %>
<li>
<% end %>
<%= link_to :controller => "home" do %>
<span>Home</span>
<% end %>
</li>
and then in each controller I just set #activeLi like this:
def index
#activeLi = "about"
end
I know this is pretty basic stuff, but i'm just wondering if there is an easier way to do this?
Well I know one way you can simplify this and thats by getting rid of the need to use those nasty instance variables.
<li class="<%= controller_name == "home" ? 'active': '' %>">
<%= link_to :controller => "home" do %>
<span>Home</span>
<% end %>
</li>
At the moment I try to do following:
I created several partials (i.e. _show_signature.html.erb) for my user.
Now I want to show them on clicking a link.
In my user controller, I created a new action:
def show_signature
#is_on_show_signature = true
end
def show_information
#is_on_show_information = true
end
on my user show.html.erb i coded this:
<% if #is_on_show_information %>
<%= render :partial => 'show_information' %>
<% elsif #is_on_show_signature %>
<%= render :partial => 'show_signature' %>
<% end %>
and in my "navigationbar" i wrote:
<ul>
<li class="profile-tab">
<%= link_to 'Information', show_information_path %>
</li>
<li class="profile-tab">
<%= link_to 'Signature', show_signature_path %>
</li>
</ul>
In my routes.rb I wrote:
map.show_information '/user-information', :controller => 'user', :action => 'show_information'
map.show_signature '/user-signature', :controller => 'user', :action => 'show_signature'
now my problem:
clicking on my "information" link will redirect me to http://localhost:3000/user-information (cause I told him this path in routes.rb - I think) and I get an error:
uninitialized constant UserController
But that's not what I want... My user show path is something like:
http://localhost:3000/users/2-loginname
(by coding
def to_param
"#{id}-#{login.downcase.gsub(/[^[:alnum:]]/,'-')}".gsub(/-{2,}/,'-')
end
in my user model)
I want to link to somethink like http://localhost:3000/users/2-test/user-information.
Any ideas how it will work? Any ideas why I get this error?
As far as Rails conventions go, the model itself is singular (User) but the table (users) and controller (UsersController) are both pluralized. This can cause a significant amount of confusion at first, and even after years of working with Rails I still make the mistake of trying things like 'user = Users.first' which is, of course, not valid, as often you get to thinking about table names instead of class names.
Also, for toggling the display of elements on a page, you probably want to use the link_to_remote method which uses AJAX for updates instead of a page refresh. If you're okay with a full page refresh, those actions will need to redirect_to something, such as the page referrer, or you will get a blank page or error since the page template does not exist.
Typically what you do is:
<ul>
<li class="profile-tab">
<%= link_to_remote 'Information', show_information_path %>
</li>
<li class="profile-tab">
<%= link_to_remote 'Signature', show_signature_path %>
</li>
</ul>
Then each action is as you have specified, however, the page template show_information.rjs would look like:
page.replace_html('extra_information', :partial => 'show_information')
Keep in mind you will need to have a placeholder to receive the partial contents, so simply wrap your optional sections in an element with a specific ID:
<div id="extra_information">
<% if #is_on_show_information %>
<%= render :partial => 'show_information' %>
<% elsif #is_on_show_signature %>
<%= render :partial => 'show_signature' %>
<% end %>
</div>