Chosen multiselect adds extra "" to array of values - ruby-on-rails

I have a form element that is using Chosen to render a multi-select input, like so
<%= f.collection_select :application_regions, ApplicationRegion.all, :identifier, :name, {}, { class: 'chosen_select', multiple: true } %>
The value of ApplicationRegions.all is an array with a single value
[#<ApplicationRegion:0x007fc61aeb3100 #identifier="FOO", #name="BAR">]
I am initializing chosen like so:
$(document).on 'turbolinks:load', ->
$('.chosen-container').remove()
$('.chosen_select').chosen
allow_single_deselect: true
width: '100%'
The input correctly displays a list with a single option BAR but the output array is ["", "BAR"] - where is that extra "" coming from, and how do I get rid of it?
I had thought that taking out the allow_single_deselect: true would take care of this, but the behavior remains (I did a spring stop just to be sure)

Зелёный was on the right track. Adding include_hidden: false to the collection_select solves the issue of the extra '' in the output.

Related

Rails 7 collection_check_boxes not displaying checked items in edit view

Pursuant to this thread, I've tried to get my code to display which items are already checked when you display an edit view. All other fields are pre-populated.
Here's how I have it currently:
%fieldset.border.border-dark.p-2.mb-4
%legend Pronouns
.row.mb-4
= f.collection_check_boxes :pronouns, pronoun_list, :itself, :itself, {include_hidden: false} do |b|
.col-md-4.d-grid.d-block.mb-2
= b.check_box(class: "btn-check", checked: #member.pronouns.split(",").map(&:itself))
= b.label(:"data-value" => b.value, class: "btn btn-outline-dark text-start btn-lg")
.form-group.mb-4
= f.label :pronouns_other, "Other Pronouns"
= f.text_field :pronouns_other, class: "form-control border border-dark"
I need to call include_hidden: false as otherwise the array contains a single blank item as the first in the array.
And here's the helper method it refers to:
def pronoun_list
[
"He/Him/His",
"She/Her/Hers",
"They/Them/Their",
"Zie/Zim/Zir",
"Sie/Sie/Hir",
"Ey/Em/Eir",
"Ve/Ver/Vis",
"Tey/Ter/Tem",
"E/Em/Eir",
"Prefer not to disclose"
]
end
The thing that's different from the other thread is that I'm using a helper method to call the collection of items from while the other thread is calling a collection of objects from the database. So I'm not sure how I'm supposed to get the id's in the first place.
#member.pronouns is a string which contains an Array (I'm using PostgresQL), so first I need to convert it to an array I assume as I read somewhere else, before I can call map on it. but while .map(&:itself) doesn't return any errors, the items that are listed in the pronouns string aren't being checked when the edit view is rendered.
Any ideas?
After some hours of wrangling with the code, and digging around for other examples, I finally got Rails to work properly.
%fieldset.border.border-dark.p-2.mb-4
%legend Pronouns
.row.mb-4
- pronoun_list.each do |pronoun|
.col-md-4.d-grid.d-block.mb-2
= f.check_box :pronouns, { multiple: true, checked: #member.pronouns.include?(pronoun), class: "btn-check" }, pronoun, false
= f.label :pronouns, pronoun, value: pronoun, class: "btn btn-outline-dark btn-lg text-start"
Explanation:
I have yet to get it to work with a collection_check_boxes; however I did get it to work with a each method and then using multiple: true on each check box.
I also set the checked_value to the pronoun and set the unchecked_value field to false. if I don't set it to false and have multiple selected, I get a bunch of zeros in the array. with false set, I only get the ones I selected in the array.
I just went through this a bit, the way collection checkboxes works is it will call first and last on object in the collection you pass it. This is so you can have a different label shown to the user and pass a different value to the server. So in your case if you created the collection like
pronoun_list = [ [Him, Him], [Her, Her] ] #contrived example
Then remove the :itself, :itself from the input. The collection checkboxes helper will then call .first and .last on each of the nested arrays using Him, Her for both the label for the checkbox and the value for the checkbox sent to the server when submitting the form
When using a collection that comes from the db to begin with like User.all you can tell collection checkboxes what to use for the value and what to use for the label eg :id and :first_name where you have :itself, :itself

Rails/ActiveAdmin form: how to disable an input field based on the value of another (boolean) input field?

I have a model that has a boolean field and an array field that gets the values populated from another model (foreign key, not really relevant to my question).
In ActiveAdmin, I have a form like such:
form do |f|
f.semantic_errors
f.inputs do
f.input :boolean_field_name
f.input :array_field_name,
as: :searchable_select,
ajax: true,
input_html: { disabled: true }
end
f.actions
end
The disabled: true works, but I would like to replace the true with something that evaluates whether or not the input checkbox for boolean_field_name has been checked on the form (which by default it isn't).
I've tried params[:boolean_field_name], params.key?[:boolean_field_name], f.object.boolean_field_name, f.object[:boolean_field_name], resource[:boolean_field_name] and resource.boolean_field_name, but they all do nothing and evaluate to nil as far as I can tell.
I've even tried ModelName.find(params[:id]).boolean_field_name but of course since params[:id] is nil that doesn't work, and it wouldn't find a record with that id anyway because the record hasn't been created yet.
I've tried looking through the ActiveAdmin repository but I can't find the information I'm looking for in the source code either.
Is this even possible?
Did you mean like this?
form do |f|
f.semantic_errors
f.inputs do
f.input :boolean_field_name
f.input :array_field_name,
as: :searchable_select,
ajax: true,
input_html: { disabled: f.object.boolean_field_name # <= does not work }
end
f.actions
end
Since the information is a bit ambiguous to me, I would firstly like to know:
From the description:
The disabled: true works, but I would like to replace the true with
something that evaluates whether or not the input checkbox for
boolean_field_name has been checked on the form (which by default it
isn't).
Did you mean that you wanna change the disabled attribute depending on the other form field after the page loads? If that's true, then you have to do it with javascript as something like this:
let booleanField = document.querySelector('booleanField'),
arrayField = document.querySelector('arrayField');
booleanField.addEventListener('change', function(e) {
arrayField.setAttribute('disabled', booleanField.value);
})
Or if you mean you just wanna set the value of the disabled attribute to what boolean_field initially is on page loads, it will bring us more information if you can debug with the tools like debug, debugger or binding.pry. It will be helpful to checkout what f.object.boolean_field_name returns. According to the information you provides, I guess it could really be nil.

Sipmle Form For - displaying a value different from the model attribute

I have a form where I wish to perform a calculation on a date before displaying it. The model has a field for start, and a method adjusted_start and adjusted_finish which I want to display instead of the raw attribute.
I've tried:
f.input :start, as: time, label: false, minute_step: 5, value: openingtime.adjuted_start
However this is over ridden with the raw 'start' attribute. Is there any way to get it to display a different value than the one it has stored for start?
Thanks in advance.
I guess it should be input_html: { value: openingtime.adjuted_start }.
You need to wrap html attributes in input_html hash.
Check out doc.

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.

How do i tell the check_box method to NOT add a hidden check_box for the 'unchecked' value?

I'm using rails 2.3.4, which, when you call .check_box on the 'f' object in a form_for, makes a visible checkbox input for the 'checked' value, and a hidden checkbox input for the 'unchecked' value: http://railsbrain.com/api/rails-2.3.2/doc/index.html?a=M002434&name=check_box
The problem with this is that i have a validates_acceptance_of validation on the check_box, and if it's not checked, i'm getting a field_with_errors div wrapped around the visible checkbox AND the hidden checkbox, so that the error message appears twice.
In this instance i don't want a value passed through in the 'unchecked' case, so i don't want rails to add the hidden checkbox - this (switching off the hidden checkbox) would solve my problem. I can't figure out how to tell it to not add the hidden checkbox though. Can anyone tell me?
I know that i could get round this by making a check_box_tag, which doesn't add the hidden 'unchecked' case checkbox, but then i don't get field_with_errors stuff wrapped around the checkbox if it's not checked. Dispensing with the hidden field seems like the cleanest solution.
Thanks - max
In Rails 4 you can use include_hidden: false
example f.check_box :some_field, include_hidden: false
Since Rails 3.2, the hidden field will not be shown if the unchecked_value argument evaluates to false.
Example: f.check_box :your_field, {}, checked_value, false
See the Rails source: 3.2,
4.1
use <%= check_box_tag "your_model[your_field]" %>
f.check_box always gives you a hidden field.
So this is interesting. check_box takes four arguments as the method definition shows:
def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
Tags::CheckBox.new(object_name, method, self, checked_value, unchecked_value, options).render
end
The checked value and unchecked value must be the third and fourth argument. By setting an unchecked_value that evaluates to a truthy value, then the hidden input will appear.
My initial goal was to have a visible checkbox with a value of true, and a hidden checkbox with a value of false. So I tried doing this:
<%= f.check_box :share, { }, true, false %>
However, because I actually passed in a boolean value for unchecked value, it made the hidden field not appear at all! I tracked it down to this line of code in the Rails source:
def hidden_field_for_checkbox(options)
#unchecked_value ? tag("input", options.slice("name", "disabled", "form").merge!("type" => "hidden", "value" => #unchecked_value)) : "".html_safe
end
If #unchecked_value evaluates to false or nil, then no hidden input field would display. Now if you want to send true and false values rather than '1' or '0' using check_box helper, then you will need to wrap the booleans in strings:
<%= f.check_box :share, { }, 'true', 'false' %>
But if that's the case, you matters well just use the defaults of '1' and '0' for boolean values and let Rails handle it.
Rails stores booleans as TinyInt, at least for the MySQL database. Consequently, that '1' will get stored in the database as 1 and will be considered a true value.

Resources