I have this HAML code adding an "active" class based on an if statement.
= link_to 'Contact Information',
edit_account_path(:contact_information),
class: ("active" if params[:section] == 'contact_information')
I want to also add a string of classes permanently, outside of the if statement.
Something like
= link_to 'Contact Information',
edit_account_path(:contact_information),
class: "Tab large", ("active" if params[:section] == 'contact_information')
I need to do this without creating a helper method because I'm not allowed to edit the code too much.
Use the ternary operator:
= link_to 'Contact Information',
edit_account_path(:contact_information),
class: "Tab large #{params[:section] == 'contact_information' ? 'active' : ''}"
The second example:
= link_to 'Contact Information',
edit_account_path(:contact_information),
class: current_page?(edit_user_registration_path) ? 'active' : ''
create a helper method say find_classes,
def find_classes(section)
default_class = ['Tab Large']
if section == 'contact_information'
default_class << 'active'
end
default_class.join(' ')
end
and from your view,
class: find_classes(params[:section])
Advantage:
you can have multiple if's and can have various classes appended.
Related
I have a link and the code is as follows:
= link_to 'Payment', account_payment_path, class:{'active'}
and I want to add a conditional logic to the view, so if the action_name is same, then add class active
I then change to the following code
= link_to 'Payment', account_payment_path, class:{'active' if action_name == 'payment'}
but it results in error. How can I fix it.?
If you want to get active links there is a gem build for that active_link_to, you can use it like this and it will handle adding the active class for you:
=active_link_to 'Payment', account_payment_path
for your problem you can use this:
= link_to 'Payment', account_payment_path, class: (action_name == 'payment' ? 'active' : '')
Try this ......
= link_to 'Payment', account_payment_path, :class => action_name == 'payment' ? 'active' : ''
Hope this will help you.
I'm late to the party, but here's what I think is more flexible, i.e. can use with any HTML tag whether it be a, li or anything.
# app/helpers/menu_helper.rb
module MenuHelper
class MenuBuilder
def initialize(template, active_class_name, active_value)
#template = template
#active_class_name = active_class_name
#active_valule = active_value
end
def item(value)
contents = #template.capture { yield }
return contents unless value == #active_value
body = Nokogiri::HTML.parse(contents).at('body')
# Method :+= does not always work because body.child['class'] could be nil
body.child['class'] = "#{body.child['class']} #{#active_class_name}"
body.inner_html.html_safe
end
end
def menu_for(active_class_name, active_value)
capture { yield MenuBuilder.new(self, active_class_name, active_value) }
end
end
Rails loads this helper automatically so that you can use it in views:
# app/views/shared/_left_sidebar.html.slim
aside
.menu
ul.list
= menu_for 'active', yield(:sidebar_menu_l1_active_value) do |m|
= m.item 'menu-1'
li = link_to 'Menu 1', '#'
= m.item 'menu-2'
li = link_to 'Menu 2', '#'
-
# app/views/home/index.html.slim
- content_for :sidebar_menu_l1_active_value, 'menu-1'
...
How to make it work ?
I need puts the two links.
Concatenation << with link_to does not.
module ItemHelper
def edit_links
if user_signed_in? && #item.user_id == current_user.id
html << link_to edit_item_path(#item), class: 'ui button small' do
"<i class='icon edit'></i> Edit"
end
html << link_to item_photos_path(#item), class: 'ui button small' do
"<i class='icon photo'></i> Photo"
end
html
end
end
end
The << operator is actually pushing an object onto an array. It also looks like the html variable is not defined yet. You create the array before your first link, then join it after your last, you should have what you need.
def edit_links
if user_signed_in? && #item.user_id == current_user.id
html = []
# ... existing logic
html.join
end
end
You'll need to start with something before you can append to it with <<, and then you'll need to call #html_safe to prevent Rails from escaping the HTML.
if user_signed_in? && #item.user_id == current_user.id
html = ""
html << link_to "<i class='icon edit'></i> Edit", edit_item_path(#item), class: 'ui button small'
html << link_to "<i class='icon photo'></i> Photo", item_photos_path(#item), class: 'ui button small'
html.html_safe
end
def show_link(link_text, link_source)
link_to link_source, { class: 'ui button small' } do
"#{content_tag :i, nil, class: 'iicon photo'} #{link_text}".html_safe
end
end
Create a helper method in application_helper and using that you can create your link_to tag.
Try this:
def edit_links
if user_signed_in? && #item.user_id == current_user.id
link_1 = link_to edit_item_path(#item), class: 'ui button small' do
"<i class='icon edit'></i> Edit".html_safe
end
link_2 = link_to item_photos_path(#item), class: 'ui button small' do
"<i class='icon photo'></i> Photo".html_safe
end
link = link_1 + link_2
end
end
In my navigation, I need '.active' to tell user if they are in the current page. So I defined a helper to generate li.active dynamically.
def nav_link(link_text, link_path
class_name = current_page?(link_path) ? 'active' : nil
content_tag(:li, :class => class_name) do
link_to link_text, link_path
end
end
so it can generate
<li class="active">
Resources
</li>
However, for one specific link, I want to add <strong> to the <a> inside <li> to make it stands out from others. How can I do it?
<li class="active">
<strong>Resources</strong>
</li>
UPDATE:
From this
To this
Every nav link(e.g. new,resources, videos) all uses the nav_link helper. What I need, is a way to insert some html(or CSS) into the resouces link. To make it stands out.
Could you not make the change in css?
.active {
font-weight: bold;
}
You can certainly nest content_tag to add strong node:
def nav_link(link_text, link_path, additional_class = nil)
class_name = current_page?(link_path) ? 'active' : nil
content_tag(:li, :class => class_name) do
content_tag(:strong) do
link_to link_text, link_path
end
end
end
Update:
You could check for "Resources" as follows to add the strong tag:
def nav_link(link_text, link_path, additional_class = nil)
class_name = current_page?(link_path) ? 'active' : nil
content_tag(:li, :class => class_name) do
link = link_to(link_text, link_path)
if link_text == 'Resources'
content_tag(:strong) { link }
else
link
end
end
end
Someone can explain me why content_tag have a different behavior in view and helpers? A simple code like the one below returns (1) when in the view, but (2) when in the Helper.
arr = ["a", "b", "c"]
concat content_tag(:ul, :class => 'a class') do
arr.each do |item|
concat content_tag(:li, item)
end
end
(1)
<ul class="a class">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
(2)
<ul>{:class=>"a class"}</ul>
When using content_tag(:ul, '', :class => 'a class') in the Helper, it renders <ul class="a class"></ul>. Why this different behavior too?
The content_tag's behavior is very confusing. I tried some magic with the capture (another confusing method!) method, but without any success.
So... any ideas?
PS.: I'm using rails 4
-------------edit--------------
Since my example is really bad, what I'm really trying to do is somethind like that:
def language_dropdown
content_tag :li, class: "dropdown language" do
concat content_tag(:a, content_tag(:span, I18n.locale, class: "username"),
class: "dropdown-toggle", data: { toggle: "dropdown", hover: "dropdown", "close-others" => "true" } )
concat( content_tag(:ul, class: "dropdown-menu") do
I18n.available_locales.each do |locale|
if locale != I18n.locale
locale_key = "translation.#{locale}"
content_tag :li do
concat(link_to I18n.t(locale_key), url_for(locale: locale.to_s))
end
end
end
end)
end.html_safe
end
This works form me...
module ApplicationHelper
def some_helper arr
content_tag(:ul, :class => 'a class') do
arr.each do |item|
concat(content_tag(:li, item))
end
end
end
end
Remove concat from first content_tag and add brackets into the inner concat method.
Update:
content_tag :li, class: "dropdown language" do
concat(content_tag(:a,content_tag(:span, I18n.locale, class: "username"),
class: "dropdown-toggle", data: { toggle: "dropdown", hover: "dropdown", "close-others" => "true" }))
concat(content_tag(:ul, class: "dropdown-menu"){
I18n.available_locales.each do |locale|
if locale != I18n.locale
locale_key = "translation.#{locale}"
concat(content_tag(:li){link_to(I18n.t(locale_key), url_for(locale: locale.to_s))})
end
end
})
end
The same thing, you need to add brackets and remove the first concat to your code...
Update 2:
items = ""
I18n.available_locales.each do |locale|
if locale != I18n.locale
locale_key = "translation.#{locale}"
items += content_tag(:li) do
link_to(I18n.t(locale_key), url_for(locale: locale.to_s))
end
end
end
label = content_tag(:span, I18n.locale, class: "username")
link = content_tag(:a, label, class: "dropdown-toggle",
data: { toggle: "dropdown", hover: "dropdown", "close-others" => "true" })
content_tag :li, class: "dropdown language" do
concat(link)
concat(content_tag(:ul, class: "dropdown-menu"){ items.html_safe })
end
I have a navigation panel. I want the class of the menu item to change to active if I click on it.
%li= { :class => current_page?(admin_roles_path) ? 'active' : nil }
= link_to "Roles", admin_roles_path
But I get the following error:
Haml::SyntaxError in Admin::Roles#index
Showing /sites/freshapp/app/views/layouts/_sidebar.html.haml where line #7 raised:
Illegal nesting: content can't be both given on the same line as %li and nested within it.
Try this (you don't need = after %li)
%li{ :class => current_page?(admin_roles_path) ? 'active' : nil }
= link_to "Roles", admin_roles_path
You don't need = after your %li and you have too mush spaces / tabs. (Haml is a nested language, number of tabs / spaces matters). Do this:
%li{ :class => current_page?(admin_roles_path) ? 'active' : nil }
= link_to "Roles", admin_roles_path
Try this
%li{ :class => "#{current_page?(admin_roles_path) ? 'active' : nil}"}
= link_to "Roles", admin_roles_path