Rails - Class not working for linkto to a controller/action - css

I needed to underline the active menu item for a submenu. I found I could use the following in my menu. I could do that by applying class:
<li><%= link_to "* RFQ", rfq_path(1), class: get_rfqs_class() %></li>
and have a helper item of
def get_rfqs_class
if controller_name == 'rfqs'
return 'active'
end
end
I have a get_xxx_class() for each item and a corresponding helper.
That works great. However, I needed to do a little different link_to for another menu item
<li> <%= link_to "Pre Production Meeting", controller:
'pre_production_meetings', action: 'show', id: 1 ,
op_id: $current_opportunity, class: get_pre_production_meetings_class() %> </li>
The problem is that the different link_to format results in the underline not showing. If I do an inspect, it does show the class as active but I don't see the underline
Pre Production Meeting
I tried using divs and spans with the following code but had no luck.
<% if controller_name == 'pre_production_meetings' then %>
<li> <%= link_to "Pre Production Meeting", controller: 'pre_production_meetings', action: 'show', id: 1 , op_id: $current_opportunity, class: get_pre_production_meetings_class() %> </li>
<% else %>
<li> <%= link_to "Pre Production Meeting", controller: 'pre_production_meetings', action: 'show', id: 1 , op_id: $current_opportunity %></li>
<% end %>
Is there something where using a link_to to a controller/action the way I did will prevent the class from being properly applied?
Also, I inspected the styles for a menu item that was working as expected
ul.art-hmenu>li>a.active {
padding: 0 12px;
margin: 0 auto;
color: #145366;
text-decoration: underline;
}
If I inspect the pre production meetings style, I don't see the a.active but see a.hover
ul.art-hmenu>li>a:hover, .desktop ul.art-hmenu>li:hover>a {
color: #000000;
text-decoration: none;
}
If I change the text-decoration to underline, then I see the underlining as expected.

That instance of link_to uses this format:
link_to(body, url_options = {}, html_options = {})
You need to surround your url options in curly braces so the link looks like this:
<a href="/pre_production_meetings/1" class="active">
Your class has been embeded into the url rather than the html.
This should solve your problem:
<%= link_to "Pre Production Meeting",
{controller: 'pre_production_meetings', action: 'show', id: 1 ,
op_id: #current_opportunity},
class: get_pre_production_meetings_class() %>
Also, the $ is probably a typo. I'm assuming it is an #.

Related

Rails 4: how to apply custom CSS to Rails form file field

I have a Rails 4 app, that uses Rails' default form (I am NOT using Simple Form).
One of my forms allows users to upload an image (thanks to Paperclip):
<td>
<%= f.file_field :image, value: "Choose a file" %>
</td>
I would like to style the "choose a file button" with custom CSS.
I tried to apply an id to my td, as follows:
<td id="upload_image">
<%= f.file_field :image, value: "Choose a file" %>
</td>
and then I tried to style it with the following CSS code:
#upload_image input {
background-color: #2c3e50;
background-image: none;
border: none;
color: #FFF;
padding: 5px 10px 5px 10px;
}
But this resulted in styling the td itself:
And I still get this ugly button with the default style.
—————
UPDATE: if styling the button itself is not possible, I would like to at least put the "no file chosen" label ("aucun fichier choisi" in French) under the button, since at the moment it is taking a lot of horizontal room on my page).
Is that even possible?
—————
How can I make this work?
This is my solution: just wrap a form field in a label and hide it.
No javascript.
<label class="btn btn-default btn-change-avatar">
Upload new image
<span style="display:none;">
<%= form.file_field :avatar, id: "fileUploader"%>
</span>
</label>
This works:
<%= f.file_field :source, :class => "ui pink button" %>
As does:
<%= f.file_field :source, class: "ui purple button" %>
You can apply styling this way. But again this, the clickable part is still going to be the default grey and say "Choose File". Aside from that, keep in mind the HTML file field is one of the least customizable up to you how much effort you want to expend trying to.
why not had a div next to the file input.... and some basic javascript
example:
<td id="upload_image">
<%= f.file_field :image, value: "Choose a file" %>
<div>Aucun fichier choisi</div>
</td>
javascript would be as follow (using jQuery):
$("#upload_image").on("change", "input", function(){
if $(this).val() == ''
$(this).closest("td").find("div").slideDown();
else
$(this).closest("td").find("div").slideUp();
});
There might be a few tweaks to do but that should get you started.
Bonne chance!
Upload Photo button with Remove button:
.d-flex.flex-row
- if #user.image.attached?
= link_to image_tag(#user.image.variant(resize_to_limit: [100, 100])), rails_blob_path(#user.image, disposition: 'attachment'), alt: 'user'
- else
= image_tag 'profile.png'
.ms-4
.d-flex.flex-row
label.btn.btn-primary
| Upload Photo
= image_tag 'Icon-Color.svg', alt: 'icon', class: 'ps-3'
.d-none
= f.file_field :image
.ps-3
- if #user.image.attached?
= link_to registration_path({ user: { id: #user.id }, purge: true }), method: :put, local: true, class: 'btn btn-primary' do
= image_tag 'Trash.svg', alt: 'icon'
.mt-1.small Up to 1 MB (300x300 px)
Result:

How can add an underline using ruby on rails and css?

I'm working with ruby on rails and I"m not very familiar with the language. What I want to do is fairly straight forward. I have a language toggle bar which allows the user to choose the language with which they can view the site.
I want to underline the selected language when it is chosen. But I'm not sure how to add a class or a span so that I can just underline (bottom-border) one of the languages.
Here is my code:
<div class="language">
<% if #language == :fr %>
<%= link_to 'English', language_path(language: :en) %>
<span>|</span>
French
<% else %>
English |
<%= link_to 'French', language_path(language: :fr) %>
<% end %>
</div>
Can someone please help me? When I select the class 'Language' it underlines both the "English|French" entirely, when all I really want is to underline the language that is currently selected. So either or, not both.
Put the active language into its own span and style it there
<div class="language">
<% if #language == :fr %>
<%= link_to 'English', language_path(language: :en) %>
<span>|</span>
<span class="selected">French</span>
<% else %>
<span class="selected">English</span>
<span>|</span>
<%= link_to 'French', language_path(language: :fr) %>
<% end %>
</div>
CSS:
.language > .selected {
text-decoration: underline;
}
You might also need to style your generated anchor tags to have text-decoration: none;, since they are probably underlined by default (as is good practice anyhow). In any case, don't use border-bottom for this.
Having said all that, I think you need to make it as clear as possible that the currently unselected language is an anchor tag. When people see underline, they tend to assume the underlined thing is a link. Conversely, things with no underline that ARE links constitute surprising behavior.

Parsing erb within erb in a view. How to add CSS class?

I have a navbar, which is showing an unread messages count. The unread count has to go within the navbar text for formatting, so I have used the below:
<li><%= link_to "My Messages #{current_user.mailbox.receipts.where({:is_read => false}).count(:id, :distinct => true).to_s}", conversations_path, class: 'small button' %></li>
How do I add a class to the count? I want to add the bootstrap navbar-unread class.
I can put:
<span class='navbar-nav'><%= current_user.mailbox.receipts.where(:is_read => false).count(:id, :distinct => true).to_s %></span>
...outside the list but then the unread count is not in the right place.
Thanks for any help, can't find an answer anywhere, or at least a better way to do this.
EDITED:
The output I need from the html would look like this:
<li>
<a class="small button" href="/converssations/link">
My Messages<span class="navbar-unread">0</span>
</a>
</li>
So I need to pass a class into a span around the ruby that starts 'current_user.mailbox...etc
It's to show the number of unread messages, which is a small number in the corner of the button.
Maybe this can help you.
Look at ActionView Helpers reference also.
<%= link_to content_tag(:span, "My Messages #{current_user.mailbox.receipts.where({:is_read => false}).count(:id, :distinct => true).to_s}", class: "navbar-nav"), conversations_path, class: "small button" %>
will have output like this
<a class="small button" href="/converssations/link">
<span class="navbar-nav">My Messages Count</span>
</a>
To achieve your mentioned behavior you can pass a block to link_to like this
<%= link_to "#your_link", class: "small button" do %>
My Message <%= content_tag(:span, "1", class: "navbar-unread") %>
<% end %>

Add an 'active' class to all active links in rails?

Basically, I have a lot of code that looks like this:
link_to t('.profile'), business_path(#business), class: '#{'active' if current_page? business_path(#business)}'
which isn't very DRY.
I was wondering if anyone knows a good way to modify the link_to helper itself to automatically add an 'active' class to all links to the current page.
If it helps, I'm open to using HAML or SLIM.
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 %>
# Main
<%= active_link_to "Main", root_path, class: "bordered" %>
# Main
<%= active_link_to "Main", root_path, class: "bordered", active: "disabled" %>
# Main
I faced same requirement and here is my solution.
Create a method within ApplicationHelper
def active_class(link_path)
current_page?(link_path) ? "active" : ""
end
And inside your view:
<li class="<%= active_class('/') %>">
<%= link_to 'HOME', root_path %>
</li>
It's a solved problem, just use active_link_to gem. Your example simplifies to this:
= active_link_to t('.profile'), business_path(#business)
This is a good case for writing your own helper that wraps the link_to. In your application_helper.rb you can write a method active_link_to that takes the same params as link_to + current_page, and then just calls link_to like you are doing above.
as per rails 6.1 now we have helper for html class name
the helper example
class_names("foo", "bar")
# => "foo bar"
class_names({ foo: true, bar: false })
# => "foo"
class_names(nil, false, 123, "", "foo", { bar: true })
# => "123 foo bar"
you could use it like this
<%= link_to 'Home', root_path, class: class_names('nav-link', { active: current_page?(root_path) }) %>
it will produce html like this
<a class="nav-link active" href="/">Home</a>
the doc is here
Here's the helper I use. I add an optional "match_text" parameter for added flexibility (for instance, if I want to mark a link as active when the actual request path is a child page of the link's destination.)
def link_to_active(text, destination, options = {})
match_text = options.delete(:match_text)
classes = options[:class].present? ? options[:class].split(" ") : []
classes << "active" if request.fullpath.downcase == destination.downcase || (match_text && request.fullpath.downcase.include?(match_text.downcase))
options = options.except(:class)
options.merge!(:class => classes.join(" ")) unless classes.empty?
link_to(text, destination, options)
end
Great solution if you're using rails 6.1+.
Also works great when passing a block.
def active_link_to(text = nil, path = nil, **opts, &block)
link = block_given? ? text : path
opts[:class] = class_names(opts[:class], { active: current_page?(link) })
if block_given?
link_to link, opts, &block
else
link_to text, path, opts
end
end
I did the same that #egyamado. I needed to use AwesomeIcons too, so:
A helper:
def active_class?(link_path)
'active' if current_page?(link_path)
end
And it was my view:
<%= link_to my_controller_page_path,
:title => "My Controller Page",
:class => "other_name_class #{active_class?(my_controller_page_path)}" do %>
<i class="fa fa-fighter-jet"></i> My Controller Page
<%end%>
In another kind of Link, for example inside a Li.
#In this case I put a extra validation in root_path
<li class="nav-class <%=active_class?(my_controller_page_path)%> <%='active' if current_page?(root_path) %>">
<%= link_to my_controller_page_path,
:title => "Page 1",
:class => "other_name_class" do %>
Page 1
<%end%>
</li>
<li class="nav-class <%=active_class?(my_controller_page_2_path)%>">
<%= link_to my_controller_page_2_path,
:title => "Page 2",
:class => "other_name_class" do %>
Page 2
<%end%>
</li>
It worked for me.
This is my custom method to handle this issue.
def active_link_to(name = nil, options = nil, html_options = nil, &block)
if current_page?(options)
active_class = html_options[:active_class] ? html_options[:active_class] : 'has-text-danger'
html_options[:class] << "#{html_options[:class]} #{active_class}"
end
link_to(name, options, html_options, &block)
end
html_options[:active_class] is a custom hash.
Now I can dynamically change styles of my active link.
<%= active_link_to "Menu", root_path, class: 'has-text-dark', active_class: 'has-text-danger' %>
Here's a basic example from which you can expand:
module ApplicationHelper
def active_link_to(text, path, **opts, &block)
css_class = opts[:class]
case opts[:endpoint]
when String then css_class.concat(' active') if current_page? opts[:endpoint]
when Array then css_class.concat(' active') if opts[:endpoint].include? request.path
end
if block_given?
link_to path, class: css_class, &block
else
link_to text, path, class: css_class
end
end
end
# app/views/layout/_navbar.html.erb
# Using multiple endpoints
<%= active_link_to 'Home', root_path, class: 'some-class', endpoint: ['', '/', '/home'] %>
# Using a single endpoint
<%= active_link_to 'Admin', admin_path, class: 'some-class', endpoint: '/admin' %>
# Using a block
<%= active_link_to admin_path, class: 'some-class', endpoint: '/admin' do %>
<h1>Administration</h1>
<% end %>
nav.slim:
li class="nav-item"
= active_link_to 'Users', users_path, "nav-link"
application_helper.rb:
def active_link_to(title, path, class_css, options = {})
if current_page?(path)
class_css = "#{class_css} active"
options.merge!('aria-current': "page")
end
link_to title, path, class: class_css, **options
end
Use link_to_unless_current and then give it the look of an active link in CSS.

Modifying <%= f.submit %>'s default CSS input class

I have been trying without much luck to get <%= f.submit %> to appear as the same as my other "buttons", all in a row. I have found this helpful post on modifying the class of f.submit, but realized upon examining its element in browser that it took on the class of input, regardless of which additional classes I added as option parameters, thus restricting its appearance.
Essentially, each of my other buttons has the following form:
<div class="sort-nav">
<ul>
<li><h4><%= link_to "Some stuff", some_link_path %></h4></li>
</ul>
</div>
And I was wondering if there is a way to fit all of these styles compacted into one class, and override that of the input class contained in f.submit. Thanks.
For edification, this button is going to be my "Follow"/Unfollow" button used to create or destroy Relationships, which I first intend to render a _follow_form partial with the following code:
<% if current_user.following?(#course) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
With each of the individual _followpartial looking like the following:
<%= form_for(current_user.relationships.build(followed_id: #course.id)) do |f| %>
<%= f.hidden_field :followed_id %>
<%= f.submit "Follow course" %>
<% end %>
a bit hackish but you can always use js to submit the form so instead of using f.submit, change it to
<div class="sort-nav">
<ul>
<li>
<h4><%= link_to_function "Some stuff", '$(this).closest("form").submit()' %></h4
</li>
</ul>
</div>

Resources