It's a problem after using the solution here
Best way to add "current" class to nav in Rails 3
def nav_link(link_text, link_path)
class_name = current_page?(link_path) ? 'current' : ''
content_tag(:li, :class => class_name) do
link_to link_text, link_path
end
end
For example, I have localhost/action1, and localhost/action2, each with a nav button.
It works great when user is in either page. In this situation, one of the button would have a 'current' css class.
But, if I set root_path to one of them, let's say is the /action1, so when user visit localhost, the button for action1 won't have a current class
How can I solve add the missing current css class when setting it as the root_path?
You can query the router itself to give you the controller and the action for the current path and just compare it to the current values from params.
def nav_link(text, path)
recognized = Rails.application.routes.recognize_path(path)
klass = "current" if recognized[:controller] == params[:controller] &&
recognized[:action] == params[:action]
content_tag(:li, class: klass) do
link_to(text, path)
end
end
You may wish to highlight your nav menu the following way - I am pretty sure this works irrespective setting the root path:
<ul>
<li class="<%= "current" if params[:controller] == "home" %>">Home</li>
<li class="<%= "current" if params[:controller] == "action1" %>">Action 1</li>
<li class="<%= "current" if params[:controller] == "action2" %>">Action 2</li>
</ul>
You may wish to replace
params[:controller]
with
params[:action]
depending on the level you wish to highlight. I have used this setup in a recent project and it worked for me. Good luck !
Related
Im having a dynamic header depending on the view and action of the controller and it works fine with the actions in "welcomes_controller". But Im not able to trigger a action from a different controller in this case posts_controller.
How can I trigger it correctly? Thanks in advance.
<% if params[:action] == 'index' %>
<%= image_tag("header_background.jpg", alt: "header background", :class => "header_background") %>
<% elsif params[:action] == 'trading' %>
<%= image_tag("trading_background.jpg", alt: "trading background", :class => "header_background") %>
<% elseif ... HOW TO TRIGGER A ACTION FROM A DIFFERENT CONTROLLER? %>
<% end %>
There are two helpers easily availalbe for this: controller_name and action_name. You can use a combo of these for conditional rendering.
That said, personally I feel this is a lot of clutter for the view - I can't help feeling this would be better set elsewhere. In a very simple sense, you could add the following in your controllers:
def index
#header_image = "header_background.jpg"
end
def trading
#header_image = "trading_background.jpg"
end
And then in the view:
image_tag(#header_image, alt: #header_image, :class => "header_background")
Alternatively, you could follow a convention for your images:
image_tag("#{controller_name}/#{action_name}.jpg", alt: action_name, :class => "header_background")
Then ensure your header images are stored in a folder named after the controller, named after the relevant action.
I'd strongly lean towards the latter.
Update: one final option would be to define a helper that handles this, something like, in you view:
= header_image_tag
And somewhere within your /helpers folder something akin to:
def header_image_tag
image_path = case controller_name
when "controller_one"
"header_background.jpg" if action_name == "index"
"trading_background.jpg" if action_name == "trading"
when "controller_two"
# ...
else
"default_image.jpg"
end
image_tag image_path, alt: # ...etc
end
I think the helper has access to controller_name and action_name, though if not you could pass these as args to header_image_tag, or pass the request as an arg and access request.controller_name and request.action_name.
Let me know what you think and how you get on.
For this I use this code. This should work for what you are trying to achieve.
<% if controller.action_name.to_s == "index" %>
Also keep in mind, if you need to be more granular with the specific controller you want to target you can also add the controller name to the check.
<% if controller.controller_name.to_s == "posts" && controller.action_name.to_s == "index" %>
I'm a beginner of rails programming.
This is my first question in sof.
I want to give my nav var "active" class when current page is included in the array of links.
I know how to check 1:1 in application_helper.rb
def is_active?(path)
current_page?(path)? "active" : ""
end
As far as I know, current_page?(x) method only show true/false.
How to check in array?
for example:
<li class="<%= is_active?([a_1_path,a_2_path,a_3_path]) %>">
I tried this:
def is_active?(paths)
y=0
for x in paths
current_page?(x)? (y=1): ""
end
y=1? "active":""
end
but this makes all the menus in nav var active.
Do I have to render other pages in one page to control and keep active class in nav var among multiple pages?
def is_active?(paths)
paths.include?(request.path) ? "active" : ""
end
Try these
<li class="<%= [a_1_path,a_2_path,a_3_path].include?(#current_page_path) ? 'active' : '' %>">
I have a simple menu that looks like this:
<ul class="menu">
<li class="active">Home</li>
<li class=""><%= link_to 'Feeds' , feeds_path %></li>
<li class=""><%= link_to 'Accounts' , accounts_path %></li>
</ul>
Class "active" is the style to mark my current page.
I have two questions:
1. How do I "tell" the app what page I am on and ask it to "change" the class to active?
2. Is there a better way to create this menu (maybe driven by the controller or a db table)?
I realize this is a newbie question, but I have been thinking about this for a few days now, have read some tutorials, but none of them really click.
Thanks for your help.
I use the method current_page? to set my active link. It takes a path as its parameter. I create a hash of link texts and paths and iterate over it printing the links. That way I only have to call current_page? one time.
There are gems that can help you, though. Look through these: https://www.ruby-toolbox.com/categories/rails_menu_builders
I have done this recently in ApplicationHelper:
def nav_links
items = [home_link, about_me_link, contact_link]
content_tag :ul, :class => "nav" do
items.collect { |item| concat item}
end
end
def home_link
nav_item_active_if(!#article || #article.type.nil?) do
link_to "Home", root_path
end
end
def about_me_link
nav_item_active_if(#article && #article.type == "About") do
link_to "About Me", article_path(About.first)
end
end
def contact_link
nav_item_active_if(#article && #article.type == "Contact") do
link_to "Contact", article_path(Contact.first)
end
end
def nav_item_active_if(condition, attributes = {}, &block)
if condition
attributes["class"] = "active"
end
content_tag(:li, attributes, &block)
end
In your view you can simply call:
<%= nav_links %>
You can maybe use it as an example.
Not a perfect solution, but you could do the following.
create 3 variables:
#homeActive = ""
#feedsActive = ""
#accountsActive = ""
In the code you provided, set the class to each variable corresponding with name.
<li class=#homeActive>Home</li>
Now in your controller under the home method lets say, set #homeActive = "active", and the other two to "". Repeat for the other methods and this should work.
I used a bunch of 'if's and the current_page? method.
It's ugly but it worked, if someone has a better idea how to do this, I will be happy to learn about it.
if current_page? (root_path)
content_tag(:li , link_to('Home' , root_path), :class => "active")
else
content_tag(:li , link_to('Home' , root_path))
end
My question is very similar to this one : Changing Current Tab in Rails
I am trying to add a 'selected' class to my link regarding the id of my portfolios controller’s show action
Here is what I've tried:
<ul>
<% for portfolio in #portfolios %>
<li class="<%= controller.class == PortfoliosController and controller.action_name == 'show' and controller.params[:id] == portfolio.id ? 'selected' : '' %>"><%= link_to portfolio.name, portfolio %></li>
<% end %>
</ul>
But it seems that the following:
controller.params[:id] == portfolio.id
doesn't match correctly and I don't understand why..
Thanks for your help!
Beware: params are always strings.
So :
controller.params[:id].to_i == portfolio.id
SideNote: extract this kind of logic in helpers, it's much cleaner.
You might be comparing string and numerical values, which in Ruby are not considered equivalent. A conversion of one of or the other might help. In fact, if you roll this up in a helper method, it might make it a lot easier to follow:
def class_for_porfolio_entry(portfolio)
controller.class == PortfoliosController and
controller.action_name == 'show' and
controller.params[:id].to_i == portfolio.id ?
'selected' :
''
end
You've got a whole lot going on there, so you might want to look at ways of reducing the complexity, for instance using params instead:
def class_for_porfolio_entry(portfolio)
params[:controller] == 'portfolios' and
params[:action] == 'show' and
params[:id].to_i == portfolio.id ?
'selected' :
''
end
This could be simplified further if you had a boolean flag set in your controller that is later used as required, avoiding hard-coding something like this:
def class_for_porfolio_entry(portfolio)
if (#show_selected_portfolio and #portfolio.id == portfolio.id)
'selected'
else
''
end
end
This presumes you have an instance variable #portfolio, which is usually the case in any controller's show method, and that you will set #show_selected_portfolio to true in any controller method where this logic applies.
Given a Rails 3 App with a menu like:
<ul>
<li>Home</li>
<li>Books</li>
<li>Pages</li>
</ul>
What is a smart way in Rails to have the app know the breadcrumb,,, or when to make one of the LIs show as:
<li class="active">Books</li>
thx
I'm not sure if I will provide you with a smart way but better something than nothing...
If your menu has some links - it is not in your example but I suppose that real menu should have links, not just the items. For example something like this in HAML: (I'm using HAML as writing ERB in text area is pure hell)
%ul
%li= link_to "Home", :controller => "home"
%li= link_to "Books", :controller => "books"
%li= link_to "Pages", :controller => "pages"
Then this helper (pasted from my project) should come handy:
#
# Shows link with style "current" in case when the target controller is same as
# current
# beware: this helper has some limitation - it only accepts hash as URL parameter
#
def menu_link_to(title, url, html_options = {})
unless url.is_a?(Hash) and url[:controller]
raise "URL parameter has to be Hash and :controller has to be specified"
end
if url[:controller] == controller.controller_path
html_options[:class] = "current"
end
link_to(title, url, html_options)
end
With this helper you can replace your "link_to" in the code above with "menu_link_to" and that's it!
An modified version of Radek Paviensky's helper is a tad simpler and more similar to link_to.
# Shows link with style "current" in case when the target controller is same as
# current.
def menu_link_to(title, options = {}, html_options = {})
if current_page?(options)
html_options[:class] ||= []
html_options[:class] << "active" # #TODO catch cases where the class is passed as string instead of array.
end
link_to(title, options, html_options)
end