Adding a class to collection_radio_buttons in Rails - ruby-on-rails

I simply have a form and at the top of my form are some radio buttons. Everything has the "form-control" class and flows perfectly fine horizontally; however, I can't get this same class applied to this:
<%= f.collection_radio_buttons :realm, [['External','External'], ['Internal','Internal']], :first, :last %>
I've been looking around, but can only find others who are doing something completely different.

Do you want the form-control class on both the button and label? Then you are looking for something like this:
<%= f.collection_radio_buttons :realm, [['External','External'], ['Internal','Internal']], :first, :last do |b| %>
<%- b.label(class: "form-control") { b.radio_button(class: "form-control") } %>
<% end %>

The syntax is
collection_radio_buttons(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
You don't have any options, so you need to supply an empty hash before the html_options hash.
<%= f.collection_radio_buttons :parent_id, [['External','External'], ['Internal','Internal']], :first, :last, {}, {class: 'form-control'} %>

Related

Rails4: collection_check_boxes from array

There is some way to serialize a collection_check_boxes from one constant?
Something like this:
# model
class tutorial < ActiveRecord::Base
serialize :option
TYPES = ["Option 1", "Option 2", "Option 3"]
end
# view
<%= form_for(#tutorial) do |b| %>
<%= f.collection_check_boxes(:option, Tutorial::TYPES, :id, :name) do |b| %>
<%= b.label class:"label-checkbox" do%>
<%=b.check_box + b.text%>
<%end%>
<% end %>
<% end %>
Or just:
<%= f.collection_check_boxes :option, Tutorial::TYPES, :id, :name %>
When I try both it I get the error:
undefined method `id' for "Option\t1":String
My permit parameters are already set with option: []
Someone did something like that before?
Thanks!
The definition is:
collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)`
The first one is a method to send, the second is a collection, the third is a method which is called to set an option value property, and the fourth is a method that is called to get a text and place it as a label for an option.
<%= f.collection_check_boxes :option, Tutorial::TYPES, :id, :name %>
There you are using Tutorial::TYPES (which is an array if strings) as a collection, and call id and name methods on each string.
Your collection should be Tutorial.all, and to get a label, you should implement a method on a Tutorial object for that, for example:
enum type: [
:type1,
:type2,
:type3,
]
And use it like this:
<%= f.collection_check_boxes :option, Tutorial.all, :id, :type %>

Change the option selected on collection_select

I'm trying to change the option that is selected on collection_select on my form in rails.
My code look like this:
<%= f.collection_select :course_type_id, CourseType.where(:deleted => false), :id, :name, {}, {class: 'form-control m-b', :selected => #course_template.course_type.name } %>
However the option selected always shows the first one and never changes unless the user selects a different option.
The resulting html looks like this:
<select class="form-control m-b" selected="selected" name="course[course_type_id]" id="course_course_type_id">
<option value="1">Driving</option>
<option value="2">Pratical</option>
</select>
Any ideas on what I'm doing wrong?
It looks like you're putting the :selected key in the html_options argument attributes.
Here is the method definition for collection_select:
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
Try this:
<%= f.collection_select :course_type_id, CourseType.where(:deleted => false), :id, :name, {:selected => #course_template.course_type.name}, {class: 'form-control m-b' } %>
<%= f.collection_select :course_type_id, CourseType.where(:deleted => false), :id, :name, { :selected => #course_template.course_type.id }, {class: 'form-control m-b' } %>
The selected parameter takes the value, and not the name of the option.
From collection_select definition, selected option and html_options are different params.
For further understanding, refer here.

How to add class to Rails select form helper when using as a block

The documentation for Rails select form helper states (see documentation):
select(object, method, choices = nil, options = {}, html_options = {}, &block)
Which allows adding a class simple, like so:
<%= f.select :some_attr, MYOPTIONS, {}, {class: 'my-class'} %>
My question is, how do I add a class to it when using it as a block? Rails documentation states:
select(report, "campaign_ids") do
available_campaigns.each do |c|
content_tag(:option, c.name, value: c.id, data: { tags: c.tags.to_json })
end
end
It doesn't work when I use it like so:
<%= f.select :some_attr, {}, {class: 'my-class'} do %>
<% MYOPTIONS.each do |MYOPTION| do %>
<%= content_tag :option, MYOPTION.label, value: MYOPTION.value %>
<% end %>
<% end %>
Nor does it work if I use:
f.select :some_attr, class: 'my-class' do
The class is not applied to the select tag in the HTML.
I solved my own problem, although I don't fully understand the answer, so if someone else understands this better, I'd love to hear your answer.
To get it to work, I simply added an additional empty hash to the beginning, like so:
<%= f.select :some_attr, {}, {}, {class: 'my-class'} do %>
<% MYOPTIONS.each do |MYOPTION| do %>
<%= content_tag :option, MYOPTION.label, value: MYOPTION.value %>
<% end %>
<% end %>
The second hash is still options and the last is still html_options, so as an example, you can also add include_blank like so:
f.select :some_attr, {}, {include_blank: true}, {class: 'my-class'}
However, I don't know what the first hash is, nor what values can be passed there. I've looked at the Rails source, but I still have no clue. If you have insight into this, I'd love to hear it.
A couple oddities to be aware of:
In your example, you're using f.select, which you can find a reference for here:
https://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/select
Only the first parameters is required, the rest have defaults. However, to assign that HMTL class, you had to have a value for the fourth parameter, which necessitated having something for the second and third parameters as well.
What you ended up with is a valid solution:
<%= f.select :some_attr, {}, {}, {class: 'my-class'} do %>
<% MYOPTIONS.each do |MYOPTION| do %>
<%= content_tag :option, MYOPTION.label, value: MYOPTION.value %>
<% end %>
<% end %>
The block, when provided, takes precedence over the literal value (an empty hash in this case).
Surprisingly, if you were rendering this tag using select_tag instead of f.select, passing a block wouldn't be an option:
https://apidock.com/rails/ActionView/Helpers/FormTagHelper/select_tag

Rails: Submit form on change

how can I get this to work?
<%= form_for current_user, html: {multipart: true } do |f| %>
<%= f.select(:brand, Brand.pluck(:company), {prompt:true}, {class: 'form-control'}, {:onchange => 'this.form.submit()'}) %>
<% end %>
The goal is to submit the form on change automatically. But the code above does not work. I get an wrong number of arguments (5 for 1..4) error. Any ideas?
The last three arguments there are actually a hash of options. Try putting them into curly braces to make it more clear, if you like:
<%= f.select(:brand, Brand.pluck(:company), {
prompt: true,
class: 'form-control',
onchange: 'this.form.submit()'
}) %>
Got it. Removed {prompt:true} and it works!
Select Helper:
select(object, method, choices = nil, options = {}, html_options = {}, &block)
This should work with prompt also:
<%= f.select(:brand, Brand.pluck(:company), {include_blank: true, class: 'form-control'}, :onchange => 'this.form.submit()') %>
Rails select helper

Setting HTML options for <option> tags in select_tag

In the following ERB:
<%= form_for #my_model do |f| %>
<%= f.select :my_attribute, options_from_collection_for_select(#my_options, :attribute, :name), {class: "select-style"} %>
<% end %>
The HTML options at the end will be applied to the generated <select> tag in the injected HTML. How can I supply HTML style options that will be applied to the injected <option> tags?
The Rails documention explains how to do this when using options_for_select, but not for when using options_from_collection_for_select.
Interesting question. Where do you get the html options from?
Say, you want a static class for all options:
<%= f.select :my_attribute, options_from_collection_for_select(#my_options.map{|o| [o.attribute,{class: 'select-style'},o.name], :first, :last) %>
of cause, you can set the class from an attribute of my_option.
The trick is, that options_from_collection_for_select also extracts html options from each element (the Hash), so you have to construct the elements to include this hash.
But then, you can as well use options_for_select (as options_from_collection_for_select does internally):
<%= f.select :my_attribute, options_for_select(#my_options.map{|o| [o.name,{class: 'select-style'},o.attribute]) %>
In my opinion this option is unavailable.
you can do this:
<%= options_from_collection_for_select(#my_options.map { |o| [o.attribute, o.name, { class: 'option-style' }] }, :first, :second) %> - but its ugly.
just do it with options_for_select:
<%= options_for_select(#my_options.map { |o| [o.attribute, o.name, { class: 'option-style' }] }) %>

Resources