Rails simple_form element with data-... attributes for stimulus? - ruby-on-rails

I am trying to hook up a stimulus controller to a form element which is inside a form generated by the simple form gem. Whatever I do - the corresponding "data-controller" attribute doesn't appear in the final rendered page (and hence, the controller won't react)...
Here's the code in question:
<%= simple_form_for book do |f| %>
<%= render 'shared/form_errors', form: f %>
...
<%= f.association :book_format, label: false, 'data-controller': 'book-format-select' %>
...
< % end %>
I also tried
<%= f.association :book_format, label: false, data_controller: 'book-format-select' %>
and
<%= f.association :book_format, label: false, html: {data-controller: 'book-format-select' } %>
None of that works - the output is always the same:
<select class="select required" name="book[book_format_id]" id="book_book_format_id">
Not sure what I am doing wrong?

You need to use input_html key
It is also possible to pass any html attribute straight to the input, by using the :input_html option
<%= f.association :book_format, label: false, input_html: { data: { controller: 'book-format-select' } } %>

Related

How can I render option field from other database table in rails?

I have a model Responsibility with has one text field of responsibility. Other model is Stage, in Stage form field there is a text_field responsibility I want to render an option list from responsibilities table how can i do that in rails?
routes.rb
resources :projects do
resources :responsibilities
resources :stages
end
stage _form.html.erb
<%= form_with(model: stage, url: [#project, stage], local: true) do |form| %>
<div>
<%= form.label :responsibility, :class=>"required" %>
<%= form.text_field :responsibility %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
How can I render responsibilities list as an option in stage responsibility form field?
what is tried is:
stage _form.html.erb
<div>
<%= form.label :responsibility %>
<%= select_tag "colors", #responsibilities , multiple: true %>
</div>
stages_controller.rb
def new
#stage = Stage.new
#project = Project.find(params[:project_id])
#responsibilities = #project.responsibilities
end
I was able to render form but in responsibility field none of the responsibility was accessed as option.
select_tag accepts as a second parameter string that contains options as a string.
Rails provides some helper methods that are useful for generation of those <option>
tags
options_from_collection_for_select, options_for_select
If you inspect with your browser's developer tools the html code of the <select> tag you will see something like this:
<select name="colors[]" id="colors" multiple="multiple">
#<Responsibility::ActiveRecord_Relation:0x00007f3f72cc7eb0>
</select>
This is because select_tag calls to_s method of #responsibilities collection.
The correct way of creating select_tag would looks something like this:
<%= select_tag "colors", options_from_collection_for_select(#responsibilities, :id, :name) , multiple: true %>
There is another way to build select field using the FormBuilder method collection_select. It might look something like this:
<div>
<%= form.label :responsibility %>
<%= form.collection_select :responsibility, #responsibilities, :id, :name, prompt: true %>
</div>
I hope this answer will be useful.

rails + simpleform: selected does not set to be enum's value

I have a enum definition for my User model.
class User < ActiveRecord::Base
enum program_of_study: [
:program_of_study_unknown, :program_of_study_cs, :program_of_study_ceg,
:program_of_study_is, :program_of_study_science,
:program_of_study_engineering, :program_of_study_fass,
:program_of_study_business, :program_of_study_others
]
end
And in simple_form I have:
<%= simple_form_for(locals[:user], wrapper: :horizontal_form, html: {class: 'form-horizontal'},
url: {action: (locals[:is_new] ? 'create' : 'update')}) do |f| %>
<%= f.error_notification %>
<%= f.input :program_of_study, collection: User.program_of_studies, include_blank: false, selected: locals[:user].program_of_study %>
<%= f.button :submit, class: 'btn-success' %>
<% end %>
However, it seems that although the program_of_study of a user is 'program_of_study_science'(by checking in rails console), when I render the form, the shown select element still has 'program_of_study_unknown' as the displayed one. The correct one was not selected.
Instead of the enum I used the keys and it seems to work, have you tried that:
collection: User.program_of_studies.keys
I didn't have to specify a selected option. My code looks like this:
input :status, as: :select, collection: Venue.statuses.keys, include_blank: false
My solution in the end
<%= f.input :program_of_study, collection: User.program_of_studies, include_blank: false, selected: User.program_of_studies[locals[:user].program_of_study] %>

rails forms updating a db record

I would like to rewrite a form which is used to update a record on a database.
I want to update the form so that the form input does not show the record, as
the record is outputted by the line
<%= q.object.content %>.
I want the
form input not to display the record, and I want that the record is updated
when the input field is edited, and is not edited when it is left blank.
I am new at working with forms and don't know the best way to achieve this.
Can anyone provide any help on achieving this ? Below is the current form. Any help would be appreciated.
<%= semantic_form_for #bunchOfThings do |f| %>
<%= f.inputs do %>
<%= f.semantic_fields_for :aThing, #aThing do |q| %>
<%= q.object.content %>
<%= q.input :content, label: "A Thing: #{q.object.content}" %>
<% end %>
<% end %>
<%= f.action :submit , label: t('Some Text'), button_html: { class: 'btn btn-primary' } %>
<% end %>
You can manually set the default value of a field to an empty string by changing this line:
<%= q.input :content, label: "A Thing: #{q.object.content}" %>
To this:
<%= q.input :content, label: "A Thing: #{q.object.content}", input_html: {value:''} %>
You would also need to filter out blank fields on the backend within the update controller method. Something like this:
def update
filtered_params = permitted_record_params
filtered_params.keep_if{|k,v| !v.blank? }
record.update(filtered_params)
...
end
Where of course the permitted_record_params method returns your permitted params hash.

Rails: Simple Form Custom Label Not Working

I'd like to create a custom label for a simple form field. For some reason, the below code isn't creating that label. It's still using the default label. I must be missing something easy.
Simple Form 3.1
<%= simple_form_for "#" do |f| %>
<%= f.input :street, label: "Custom Label" %>
...
<% end %>
How can I create a custom label for my inputs in Simple Form?
You need to use a label helper along with your input helper:
<%= simple_form_for "#" do |f| %>
<%= f.label :street, 'Custom label' %>
<%= f.input :street, as: :string, label: false %>
<% end %>
You can also directly specify input types ie. f.text_field - More info : http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
You can now pass a label as argument. So the syntax as shown in the question (from 2015) now works:
<%= f.input :street, label: "Custom Label" %>
See the "Usage" section of the readme.

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