How to set a default attribute on Rails select form helper? - ruby-on-rails

I am trying to override Rails' select method with a custom form helper, so that all select boxes get a disabled attribute by default:
class LabelFormBuilder < ActionView::Helpers::FormBuilder
def select(method, choices, options = {}, html_options = {})
html_options.reverse_merge! :disabled => true
super(method, choices, options = {}, html_options = {})
end
end
The problem is that the code is not working and that it doesn't change anything in the way the select boxes are rendered. It doesn't throw an error either.
This would be the view code that I use to call the function:
<%= f.select(:person_id, current_user.person_names, {:prompt => 'Please select...'}) %>
What am I missing here?
Thanks for any help...

Try it maybe with
<%= f.select(:person_id, current_user.person_names, {}, {:prompt => 'Please select...'}) %>

Related

f select multiple select is not working using in form

I have working on project using ruby on rails. I have created a form with many fields and one field is for jobs where I want to choose more then one job but now I am not able to choose more then one job with following code. Working with ruby on rails 3 and HAML. I also mention multiple true but still its not working.
= f.select :jobs, options_from_collection_for_select(Demojob.all, 'name','name' ), :multiple => true
If you check the implementation of the form builder select method (github), you'll see that the method signature is:
select(method, choices = nil, options = {}, html_options = {}, &block)
multiple flag should be passed using html_options hash, not options. In your case, it should be:
f.select :jobs, options_from_collection_for_select(Demojob.all, 'name', 'name'), {}, :multiple => true
Or, even better, if you prefer new hash syntax:
f.select :jobs, options_from_collection_for_select(Demojob.all, 'name', 'name'), {}, multiple: true
Lastly, there's no need to use options_from_collection_for_select with form builder, you can simply pass the options as arrays:
f.select :jobs, Demojob.all.collect { |job| [job.name, job.name] }, {}, multiple: true
Cheers!

rails collection_select should print my collection

I got an error while trying to use collection_select ;)
I got this code in my view:
<%= f.collection_select(:channel, :channel_id, #channels, :id, :channelname, prompt: true) %>
in my controller I have this:
#channels = Channel.all
and I got this error:
undefined method `merge' for :channelname:Symbol
Whats my failure ?
Thanks at all!
According to the docs:
collection_select(method, collection, value_method, text_method,
options = {}, html_options = {}) public
So therefore you should use:
<%= f.collection_select(:channel_id, Channel.all, :id, :channelname, prompt: true) %>
You can use like
Channel.all.pluck(:id, :channelname)
For example take look at below
collection_select(
:post, # field namespace
:author_id, # field name
# result of these two params will be: <select name="post[author_id]">...
# then you should specify some collection or array of rows.
# It can be Author.where(..).order(..) or something like that.
# In your example it is:
Author.all,
# then you should specify methods for generating options
:id, # this is name of method that will be called for every row, result will be set as key
:name_with_initial, # this is name of method that will be called for every row, result will be set as value
# as a result, every option will be generated by the following rule:
# <option value=#{author.id}>#{author.name_with_initial}</option>
# 'author' is an element in the collection or array
:prompt => true # then you can specify some params. You can find them in the docs.
)
try this
<%= f.collection_select(:channel_id, :id, prompt: true) %>

Front end validation for rails select field

Select Field:
<%= f.select :study_material_type, StudyMaterial::TYPES.map{|v| [v,v]}, selected: f.object.try(:study_material_type) , required: true,include_blank: "Please select a Study Material"%>
I want to validate the presence of :study_material_type select field. How can I do this?
Select takes in 5+ options while required validation is a html_option
i.e
select(object, method, choices = nil, options = {}, html_options = {}, &block)
put the html arguments in { } as a html_options. This should work for you.
<%= f.select :study_material_type, StudyMaterial::TYPES.map{|v| [v,v]}, {include_blank: "Please select a Study Material"}, {required: true } %>
Here is a good material for you to understand better.

get selected items from select_tag

I have this line in my rails app:
<%= select_tag :questionnaire_id,
options_for_select(#questionnaires_types, #questionnaires_ids),
:multiple => true, :size => 7 %>
which works fine.
but when I try to use the multiple values that were selected I get this:
questionnaire_id"=>["1687,1688,1689,1690,1691,1724"]
instead of this:
questionnaire_id"=>["1687", "1688", "1689" ,"1690", "1691", "1724"]
i.e. I get 1 item instead of 6 items.
any suggestions?
According to rails code: https://github.com/rails/rails/blob/41231ef6c6c6a6e546b69add28f04aafb9e0e952/actionview/lib/action_view/helpers/form_tag_helper.rb#L134
The name must end with [] to be make sure you receive an array.
def select_tag(name, option_tags = nil, options = {})
option_tags ||= ""
html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
if options.delete(:include_blank)
option_tags = content_tag(:option, '', :value => '').safe_concat(option_tags)
end
if prompt = options.delete(:prompt)
option_tags = content_tag(:option, prompt, :value => '').safe_concat(option_tags)
end
content_tag :select, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
end
So just change it to questionnaire_ids[]
Hope that helps.
I think a collection_select would look nice but I cannot help with that since you did not post anything about the model. Maybe try this so that it knows it is a collection:
<%= select_tag "questionnaire_ids[]", options_for_select(#questionnaires_types, #questionnaires_ids), :multiple => true, :size => 7 %>
Or you could just parse the string you currently receive using #split.
Otherwise post a bit more code about the associations between Questionnaire and what ever this model is.
Well, just in case that someone will come to this issue, I found the problem.
It seems to be a bug in rails.
I was using remote_form_for, and that gave me the strange behaviour. I tried to change the form to form_for instead, and I got an array with 6 items.
Rails, Rails, when will you be like .Net? :-(

Show ajax based elements after form submit error

I have two select elements in my form, Category and Sub-category. At first, only the category select is shown. When the user makes a selection in the category select, an AJAX request is sent to the server and the subcategory select is shown. It works fine.
Now, when there is some error in the form submit, due to anything, missing some value that is required, or anything, I show the error message, but I cannot retain the same state of the select boxes, I see only the category select, with no value selected, i.e the initial state. Can anyone suggest me how I can preserve the state of these select elements?
Here's a code snippet from my new form:
<div id="category-select">
category <%= collection_select :post_category, :id, #categories, :id, :name,
options = {:prompt => "Select a category"} %>
</div>
<div id="sub-category-select">
</div>
Here's my jQuery script that sends AJAX request when a selection is made on Category select:
$("#post_category_id").change(function() {
var category_id = $('select#post_category_id :selected').val();
if(category_id == "") category_id="0";
$.get('/posts/update_sub_cat/' + category_id, function(data){
$("#sub-category-select").html(data);
})
return false;
});
The AJAX request is made on the update_sub_cat action in the post_controller, which is shown below:
def update_sub_cat
if params[:id].present?
#sub_categories = Category.find_all_by_parent_id(params[:id])
else
#sub_categories = []
end
respond_to do |format|
format.js
end
end
The AJAX request renders update_sub_cat.js.erb file, in which I have used some HMTL
sub-category <%= collection_select :post_sub_category, :id, #sub_categories, :id, :name,
options = {:prompt => "Select a sub-category"} %>
I know, I should not directly use HTML here, but rather use $('sub-category-select).append(...), but I got it working like this, and am planning to change it later.
This is all the code that is involved in this part of my program.
Can anyone help me, please?
I solved the problem, and got the AJAX based element to maintain state. Here's my jQuery code:
$('#before_category_select').loadPage();
jQuery.fn.loadPage = function(){
if($("#new-post-area").length > 0){
$.getJSON('/home/cat_select_state.json', function(data){
$.get('/posts/update_sub_cat/' + data.cat_state, function(data1){
$("#sub-category-select").html(data1);
})
});
}
}
The controller action that I call to get the state of the select elements, which is stored as session variables at the time of page submit:
def cat_select_state
#cat_session = {:cat_state => session[:new_post_category], :sub_cat_state => session[:new_post_sub_category]}
respond_to do |format|
format.json {render :json => #cat_session}
end
end
And finally, I used a default values for the select boxes, which are stored as session variables. If the session variable is null, the default value is the prompt message for the select box.
<%= collection_select :post_category, :id, #categories, :id, :name,
options = {:prompt => "Select a category", :selected => session[:new_post_category]} %>
The HTML for sub-category select element is rendered in the javascript file update_sub_cat.js.erb.
sub-category <%= collection_select :post_sub_category, :id, #sub_categories, :id, :name,
options = {:prompt => "Select a sub-category"} %>
Please suggest if you have any more improvements.

Resources