I am probably missing something really simple, but would appreciate a little help here
<%= select_tag('filters[order_sales_channel]',filter_params['order_sales_channel'],:multiple=>true,:class=>"advancedSearchFormSelectBox") %>
I then want to give the options for select
<option value="Web">Web</option>
<option value="Phone">Phone</option>
How can I achieve this? I tried this but it wasn't working
<%= select_tag('filters[order_sales_channel]',filter_params['order_sales_channel'],:multiple=>true,:class=>"advancedSearchFormSelectBox") %>
<%= options_for_select([["Web", "Web"], ["Phone", "Phone"]]) %>
Follow up question -: Since I am using the select option in multiple places where my option value is same as the printed string, is there a better way to go about this?
The correct way to do this is :
<%= select_tag 'filters[order_sales_channel]',
options_for_select(
[["Web", "Web"], ["Phone", "Phone"]],
selected: filter_params['order_sales_channel']
),
multiple: true,
class: "advancedSearchFormSelectBox" %>
if your options will always be the same, just hardcode them in the relevant class:
class Order < ActiveRecord::Base
SELECT_OPTIONS = %w[Web Phone].map( &:freeze ).freeze
def self.select_options
SELECT_OPTIONS.map{|o| [o,o] }
end
end
then you can use this in your options_for_select :
options_for_select Order.select_options
I like this solution because you can also use SELECT_OPTIONS in validations :
validates :some_attribute, inclusion: SELECT_OPTIONS
Related
<%= form_for(:offer,:url=>{:controller=>'offers',:action=>'combo'}) do |f|%>
<%= f.select :catId_get, options_from_collection_for_select(#categories, "id", "name"), prompt: "Select Category" %>
I am new in rails.I have a dropdown where all categories are there.When i select a category from this dropdown i want to get its category id in my controller,so that i can use that id for it's child dropdown.
Select
Each select option in HTML has two values -- the value and the label:
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
It's only the value which is passed to your controller. This means if you are able to create the select tag in your Rails app with the correct value / label setup, it will pass the correct data you require.
Rails
Here's how I'd handle it:
<%= form_for :offer, offers_combo_path do |f|%>
<%= f.collection_select :cat_id, #categories, :id, :name, prompt: "Select Category" %>
This will pass the following params to your categories_controller:
#app/controllers/categories_controller.rb
class CategoriesController < ApplicationController
def combo
params[:offer][:cat_id]
end
end
Recommendation
I'd actually recommend you use the form_tag helper for this, rather than form_for. Reason being that form_for is mainly for ActiveRecord objects, and although you can use :symbols in the helper, you will really need to use a much less elaborate system
I'd just replace your form_for with the following:
<%= form_tag offer_combo_path do %>
<%= collection_select :cat_id, #categories, :id, :name, prompt: "Select Category" %>
<% end %>
Your id should be accessible by
params[:offer][:catId_get]
in your controller.
I declare a model with an enum type like:
class Event < ActiveRecord::Base
enum event_type: { "special_event" => 0,
"pto" => 1,
"hospitality" => 2,
"classroom" => 3
}
Then in my update view, I have a form with:
<%= simple_form_for #event do |f| %>
<%= f.input :event_type, collection: Event.event_types.keys %>
...
<% end %>
This works great, and I get a select populated with my enumerated types.
When I perform the #event.update(event_params) in my controller, I can check the db and see that the event_type field has been updated to the correct integer value.
However, when I revisit the edit page, the select shows a nil value. If I check its value by adding a debug line to my form:
<%= f.input :event_type, collection: Event.event_types.keys %>
<%= debug #event %>
I see that the value for event_type is correct:
--- !ruby/object:Event
attributes:
...
event_type: '2'
but the input selector is still blank rather than showing "hospitality" as it should.
Any ideas would be greatly appreciated. :)
this line worked just fine. <%= f.input :event_type, collection: Event.event_types %>
Do you have to manually set the selected value ?
what's your version of simple_form ?
Vincent's solution gives me the error: '0' is not a valid 'fieldname'
I had to add keys as suggested in other stackoverflow post:
<%= f.input :event_type, collection: Event.event_types.keys %>
Use the enum_help gem. Lets you do this:
<%= f.input :event_type %>
I got stuck on this one too. I needed to titlieze my enums so they wouldn't look so wonky with the snake_case that I was using. I used to_a to take the ruby hash and turn it into an array and then I used collect to return a new array in the format that I needed.
collection: Event.event_type.to_a.collect{|c| [c[0].titleize, c[0]]}
Hopefully this will help someone else out.
Thanks for following this up. I believe the issue I reported was caused by an incorrect declaration for event_type. In my migration, I had accidentally defined event_type as String rather than an Integer:
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
...
t.string :event_type
...
end
end
end
I believe that enum's should be declared as integers to work correctly. Unfortunately, I did not test that changing the type to integer makes it work because I actually ended up using a different approach. Rather than using an enum I instead defined my collection of event types in my model:
class Event < ActiveRecord::Base
def self.types
['Special_Events', "On-Going", 'PTO', "Classroom"]
end
...
end
And, then in my form, used simple form with this syntax:
<%= f.input :event_type, collection: Event.types, input_html: { autocomplete: 'off' } %>
And all worked well.
I'm using draper as decorator, so I'd like to add words translation into model's decorator. Here is my code:
app/decorators/meter_decorator.rb
class MeterDecorator < Draper::Decorator
delegate_all
STATUS_MAPPING = {
uninitialized: '未安装',
good: '良好',
broken: '故障',
disabled: '禁止'
}
def status
STATUS_MAPPING[object.status.to_sym]
end
end
views/meters/_form.html.erb
<%= f.input :status, collection: MeterDecorator::STATUS_MAPPING, label_method: :last, value_method: :first, include_blank: false %>
views/meters/index.html.erb
<td><%= meter.decorate.status %></td>
For example, assuming you have an enum like this one in your model (Model Role in the example):
enum :work_type, in_person: "in_person", remote: "remote", hybrid: "hybrid"
This will work in your view
= f.input :work_type, as: :select, collection: Role.work_types.collect { |key, value| [key.to_s.titleize, value] }
This will out put the following HTML:
<select class="form__input" name="role[work_type]" id="role_work_type">
<option selected="selected" value="in_person">In Person</option>
<option value="remote">Remote</option>
<option value="hybrid">Hybrid</option>
</select>
With some more research, I came up with the following solution:
<%= f.input :event_type, collection: Event.event_types.keys,
:selected => Event.event_types.keys[#event[:event_type].to_i],
input_html: { autocomplete: 'off' } %>
So, I had to do 2 things:
Use :selected to set the value of the selector. This required the cumbersome syntax Event.event_types.keys[#event[:event_type].to_i] to set the select value. I'd love to hear if there is a simpler syntax I could have used. :)
Set autocomplete: 'off' to prevent firefox from wanting to set the selector to its previous setting on a page reload.
Alternate, simpler solutions would be welcomed!
how can we define id for this rails select statement , i have tried doing in this way like
<%= f.select :state, options_for_select(Contact::STATES), :id=>"state_job" %>
but it is not showing any id when i inspect it in the browser. Please help me out
<%= f.select :state, options_for_select(Contact::STATES) %>
The select tag helper looks for options, then html_options, you just need to make sure your id is in the right place (html_options) by passing something to the options parameter:
<%= f.select :state, options_for_select(Contact::STATES), {}, {:id=>"state_job"} %>
I need to add a custom HTML attribute to each option for a select control. I'm using simple_form in Rails. Does anyone know how to do this? The attribute will be consumed by client-side JS.
For instance, I want to do something like this:
<%= f.input :group, collection: #groups, option_html: { data-type: lambda { |g| g[2] } } %>
Which would produce (simplified):
<select>
<option value="1" data-type="primary">First Group</option>
<option value="2" data-type="secondary">Second Group</option>
<option value="3" data-type="secondary">Third Group</option>
</select>
Where #groups might look like this:
[
['First Group', 1, 'primary'],
['Second Group', 2, 'secondary'],
['Third Group', 3, 'secondary']
]
Hoping to avoid having to make a custom control/wrapper. Thanks!
You're close! easiest way is actually not using simple_form here. here's the simple_form documentation
<% options = #group.map { |g| [g.name, g.id, {'data-type' => g.group_type}] } %>
<%= f.input :group, label: 'Group' do %>
<%= f.select :group, options, include_blank: 'Select a Group', class: 'form-control' %>
<% end %>
For your exact code it would be:
<% options = #group.map { |g| [g[0], g[1], {'data-type' => g[2]}] } %>
<%= f.input :group, label: 'Group' do %>
<%= f.select :group, options, include_blank: 'Select a Group', class: 'form-control' %>
<% end %>
simple-form only:
= f.input :group, #groups.map{|l| [l[0], l[1], {data: {type: l[2]}}]}
A (small) drawback using f.input do end method is that any default input html options (like simple form's required or optional classes or the required attribute) and any default options (like b.use :input, class: 'input-element') are missing when simply passing a block to f.input, tldr: the input does not get decorated.
If you rely on these extra classes and attributes, you'd have to manually pass them in (not dry).
To overcome this I've created a custom input for my special selects, so I can define the body of my select like I want (the <option> tags) but the select gets decorated as usual:
# app/inputs/select_container_input.rb
class SelectContainerInput < SimpleForm::Inputs::Base
def input(wrapper_options)
options_html = input_options.delete(:options_html)
# since we pass our options by our self (and have to select the correct
# option), set `selected` to `''` to prevent rails calling
# `object.send(attribute_name)` only to set `selected` which is not used.
input_options[:selected] = ''
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
#builder.select attribute_name, nil, input_options, merged_input_options do
options_html
end
end
end
Simply call it like this:
<% options_html = capture do %>
<option>bla</option>
<% end %>
<%= f.input :attribute, as: :select_container, options_html: options_html %>
The options_html is a workaround, because actually it would be easier to pass in a block to our custom input:
<%= f.input :attribute, as: :select_container do %>
<option>bla</option>
<% end %>
But due to the way SimpleForm::FormBuilder#def_input works, the block gets carried away before code even touches the inputs. So no way without refactoring simple_form.
All in all this solves the problem with a little bit extra noisy code in your views for your special selects.
For an association select:
f.association :product, collection: Product.all.map { |product| [product.name, product.id] }
This seems to be the correct way of doing this:
Rails Simple Form custom association select field
I need to add a class to my select.It seems to be easy but I'm not able to figure it out.
I'm trying this but the class doesn't show up:
<%= f.select :dr_state, us_states ,:selected=>cr_dovi.try(:dr_state),:class=>"dr_state" %>
When I don't need to make that select auto-select It works in this way:
<%= f.select :dr_state, us_states ,{},:class=>"dr_state" %>
I have been trying to figure it out for about an hour please help me.
Try the following, I think Ruby may be parsing both of your final parameters into the same hash:
<%= f.select :dr_state, us_states , { :selected=>cr_dovi.try(:dr_state) }, :class=>"dr_state" %>