Rails 4 - Display choices as radio buttons - ruby-on-rails

I am working on a Rails 4 application, using simple_form for input. There are several model fields that can take well-known answers or a free-form answer. For example, for a field fruit:string I would like to display "Apple", "Banana", "Other". If the user chooses "Other", they can enter any free-form text. Currently, all I can do is use <%= f.input :fruit %> and a blank textbox shows up. Is it possible to show radio buttons instead? I can do
<%= f.collection_radio_buttons :fruit, [["Apple", "Apple"], ["Banana", "Banana"]], :first, :last %>
but that does not provide the "Other" option. The goal is to record "Apple", "Banana" or the specified (typed-in) value if "Other" was chosen.

Simple Form lets you us as: :radio_buttons on a collection, like so
<%= f.input :fruit, collection: ['apple', 'banana', 'other'], as: :radio_buttons %>
See the collection section of the SimpleForm README for more information on collection inputs.

One solution would be to have the f.collection_radio_buttons followed by the f.input, both with the same name. Then, selectively enable the f.input based on the selected radio button with jquery or javascript. For this to work, you would probably also want to add an ['Other']['Other'] option.
EDIT
Maybe something along these lines:
f.collection_radio_buttons :fruit, [['Apple','Apple'],['Orange','Orange'],['Other','Other']], :first, :last
f.text_field :fruit
$("input:radio[name='foo[fruit]']").change(function(){
if($(this).val() == 'Other'){
$("input:text[name='foo[fruit]']").show().prop( "disabled", false);
}else{
$("input:text[name='foo[fruit]']").hide().prop( "disabled", true );
}});
Because they have the same name, Rails will use the last value (the text field in this case if it is enabled), otherwise it will use the selected radio button.

Related

Field gets radio button's item id instead of its value

I have snippet:
<%= f.input :purpose, as: :radio_buttons, collection: category.subcategories,
wrapper: :vertical_collection_inline %>
which lines values of category.subcategories horizontally how I want
The problem is, when I select either of option, it assigns that option's ID, but not its value.
How should I refactor the code?
Using IDs has advantages as warned in the comments, however what you’re trying to do should work with either:
category.subcategories.collect(:&values)
Where values is the name of the field which hols “Rent” etc.
The more railsy way to do this is with collection_radio_buttons, like this:
f.collection_radio_buttons(:purpose, category.subcategories, :value, :value)
Again where “value” is the field name.

simple_form checkboxes collection with "other" checkbox

I use simple_form and have this in my form code:
<%= f.input :fruit, as: :check_boxes, collection: ['Apple', 'Orange', 'Other'] %>
So I want to have a text input associated with 'Other' field next to it, so that user can click 'Other' and enter his own fruit name. How do I do it?
I tried it like f.input(...) as one of collection items, I've also tried adding it in do block, but it all seems like totally irrelevant.
How do I get the behavior I want? Thank you.
You can do this:
# view
<%= text_field_tag :alternative_fruit %>
# controller
if params[:alternative_fruit].present? && params[:your_model_name][:fruit].select(&:present?).blank?
params[:your_model_name][:fruit] = params[:alternative_fruit]
end
This will overwrite the fruit name if you didn't select a checkbox with the alternative name, if you defined one.

In simple_form, can't submit boolean as radio_button if the field is disabled

I am using simple_form 2.0. I have a Boolean field 'stock' which I am trying to submit as radio buttons.
<%= f.input :stock , :as => :radio_buttons, :collection => [['Purchase Indent', false],
['Stock', true]], label:"Shipments From" , :disabled => true%>
The stock is marked as false before rendering the form.
Once I submit the form the stock itself is missing from the parameter and I get this error.
Because I am validating stock's inclusion.
validates_inclusion_of :stock, :in => [true, false]
It works fine if i don't disable the field. But I don't want user to be able to change it.
Please help.
Update
The reason is that, the disabled fields are never sent. http://www.w3.org/TR/html401/interact/forms.html#h-17.12
Seems like making it read-only will help.
https://github.com/plataformatec/simple_form/pull/367
But, the news is radio buttons can't be made read only.
Why can't radio buttons be "readonly"?
One option is to separate the buttons and only disable the unselected option:
<%= f.input :stock , :as => :radio_buttons, collection: [['Purchase Indent', false]], label:"Shipments From" %>
<%= f.input :stock , :as => :radio_buttons, collection: [['Stock', true]], label:"" , :disabled => true %>
Another option would be to add a hidden input with the desired value.
Remember not to trust user submitted data.
I don't think you should build it like this, because a hacker can just change the HTML / submit an artificial request even if you disable the form elements. Hidden form elements don't fix this, as anyone with a dom explorer can change the values. Of course, if your model checks and rejects this kind of thing it's not such a big problem.
So to fix the particular problem, just do the visuals as you have already, and re-insert the expected value in your controller's update or create action.
For more info there's lots online e.g. owasp, but I liked the book "How to break web software" from a few years back by some guys at Google.

How to have a collasped drop down list in rails simple_form

In my app, there are two models: rfq and standard. Their relationship is many-to-many. In rfq creating screen, the code below displays a list of available for selection in drop down list:
<%= simple_form_for #rfq do |f| %>
<%= f.association :standards, :collection => Standard.active_std.all(:order => 'name'), :label_method => :name, :value_method => :id %>
<% end %>
The problem is that the list is not collapsed, which means there are multiple standards displayed in a multi-line boxes. How can I reduce the box to one line only?
Thanks.
UPDATED: here is the screen shot of multiple line list box:
It's creating a multi-select because one rfq can have many standards, so it allows you to ctrl-click to select many standards.
You could try adding :input_html => { :size =>'1' } but I'm not sure that will preserve the scrollbar. It definitely won't drop down.
Here's someone else who wanted to do the same thing: HTML muliple select should look like HTML select. One of the answers refers to a Dropdown Check List implemented in jQuery, but that would take some work to integrate with SimpleForm.
SimpleForm has a very helpful Google Group--you might get more ideas there:
http://groups.google.com/group/plataformatec-simpleform
You can add as: :collection_select
Use
=f.collecion_select, model_associated_ids, collection, value, label
in your is like this
=f.collection_select, :standard_ids, Standard.active_std.all, :id, :name
you can find more info here
https://github.com/plataformatec/simple_form

collection_select set option value of :include_blank to zero

In my rails app, i have a drop down box where i retrieve all groups from the Group table and display them using the collection_select tag.
When the user selects 'None', I want to pass '0' as option value.
Currently, an empty string is passed.
Is there a way to include option value = 0 for 'None'?
<%= f.collection_select :SUB_GROUP, Group.all, :Group_ID, :Group_ID, :include_blank => 'None' %>
Many many thanks for any suggestion provided
If you use options_for_select in combination with select_tag you can achieve that using this:
options_for_select(
[['None', '0']].concat(
Group.all.collect { |g| [g.group_id.to_s, g.group_id.to_s] }
)
)
In order to keep your views uncluttered, you might want to generalize and move this into a helper method with a reasonable name.

Resources