Ability to make associations and collections required #340

Closed
jeromewilson opened this Issue Sep 30, 2011 · 19 comments

Projects

None yet

5 participants

@jeromewilson

Setting associations and collections to be required doesn't seem to have any effect on validation at the moment. A default blank option is still displayed, selectable and saveable.

@rafaelfranca
Collaborator

Could you, please, post the HTML of the generated select inputs?

@mskraddoc

Seems collections get select class="select optional"

This code:

<%= simple_form_for @protocol do |f| %>
  <%= f.input :name , :label =>"Protocol Name", :hint=>"Enter a new protocol name here."%>  
    <%= f.input :modality_id, :collection => Modality.all%>
  <%= f.hidden_field :user_id, :input_html => { :value => current_user.id }  %>  
  <%= f.button :submit %>  
<% end %>

generates this html

    <form accept-charset="UTF-8" action="/protocols" class="simple_form protocol" id="new_protocol" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /><input name="authenticity_token" type="hidden" value="F9WMX51rNJRewpCHZM9rSsz+0ZYw8G43hzPCT8kLm/0=" /></div>
  <div class="input string required"><label class="string required" for="protocol_name"><abbr title="required"></abbr> Protocol Name</label><input class="string required" id="protocol_name" maxlength="255" name="protocol[name]" required="required" size="50" type="text" /><span class="hint">Enter a new protocol name here.</span></div>  
    <div class="input select optional"><label class="select optional" for="protocol_modality_id"> Modality</label><select class="select optional" id="protocol_modality_id" name="protocol[modality_id]"><option value=""></option>

<option value="1">MRI</option>
<option value="2">CT</option>
<option value="3">Ultrasound</option>
<option value="4">Radiograph</option></select></div>
  <input id="protocol_user_id" input_html="{:value=&gt;5}" name="protocol[user_id]" type="hidden" value="5" />  
  <input class="button" id="protocol_submit" name="commit" type="submit" value="Create Protocol" />  
</form>
@rafaelfranca
Collaborator

Do you have validates :modality_id, :presence => true in your model?

@mskraddoc

Thanks for your reply.
I did not.
I put validates :modality_id, :presence => true in my model.
The form still does not generate an error, but at least now the 'create' action fails.

@mskraddoc

Interestingly, if I put :required=>true as the first argument, the html generated does indicate class=required, but not selecting the drop down still produces no error.

code is:

<%= simple_form_for @protocol do |f| %>
  <%= f.input :name , :label =>"Protocol Name", :hint=>"Enter a new protocol name here."%>  
    <%= f.input :modality_id, :required=>true, :collection => Modality.all, :prompt=>"Select Modality"%>
  <%= f.hidden_field :user_id, :input_html => { :value => current_user.id }  %>  
  <%= f.button :submit %>  
<% end %>

html is:

    <form accept-charset="UTF-8" action="/protocols" class="simple_form protocol" id="new_protocol" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /><input name="authenticity_token" type="hidden" value="F9WMX51rNJRewpCHZM9rSsz+0ZYw8G43hzPCT8kLm/0=" /></div>
  <div class="input string required"><label class="string required" for="protocol_name"><abbr title="required"></abbr> Protocol Name</label><input class="string required" id="protocol_name" maxlength="255" name="protocol[name]" required="required" size="50" type="text" /><span class="hint">Enter a new protocol name here.</span></div>  
    <div class="input select required"><label class="select required" for="protocol_modality_id"><abbr title="required"></abbr> Modality</label><select class="select required" id="protocol_modality_id" name="protocol[modality_id]"><option value="">Select Modality</option>

<option value="1">MRI</option>
<option value="2">CT</option>
<option value="3">Ultrasound</option>
<option value="4">Radiograph</option></select></div>
  <input id="protocol_user_id" input_html="{:value=&gt;5}" name="protocol[user_id]" type="hidden" value="5" />  
  <input class="button" id="protocol_submit" name="commit" type="submit" value="Create Protocol" />  
</form>
@rafaelfranca
Collaborator

But, without the required option and with validates :modality_id, :presence => true in the model the required class is added?

@mskraddoc

Yes. That is correct. When I add validates :modality_id, :presence => true to the model, the required class is added. Still, no selection from the drop-down will send "modality_id"=>"" in params as verified by webrick log and program behavior. I suppose I can handle the error and redirect to the form again, but I wish the required class was functional. Perhaps this not a simple_form only issue?

@rafaelfranca
Collaborator

No. SimpleForm do not handler any error. This is responsibility of you application. It only mark with required class.

@rafaelfranca
Collaborator

We don't change anything on your select inputs because, if we remove the blank select, your users might select an option that they don't want to.
So, we leave the choice of remove the blank option to you.

@mskraddoc

Got it. Understandable.

If you wanted to help many others, you could consider the following:

If ( (:prompt is set to a value) && (:required==true) && (selected_value==:prompt) )

... then flag an error similar to when other required fields are left blank.

Thanks for letting me use simple_form. It definitely cleans-up my code. Much appreciated -

Perry

@mikebridge

I have a conditional validation which I implemented by adding ":required" to my select:

<%= f.input :age, :collection => 18..60, :prompt => "Select your age", :required => true %>

However, this added a "required" class, but didn't add the "required" attribute to the select tag. I got it to work by passing the attribute through:

<%= f.input :age, :input_html => {:required => true}, :collection => 18..60, :prompt => "Select your age", :required => true %>

Is this by design?

Thanks,

-Mike

@rafaelfranca
Collaborator

If the value of config.browser_validations or config.html5 is false the required attribute is not added by SimpleForm.

@mikebridge

Yes, I have those values set to true by default, and I am connected to a Model which also has certain string fields marked with "validates_presence_of"---these get validated fine. But I have a "belongs_to" which is not required in the Model, but is required in the controller/view. When I mark it the "select" as :required (as per my example below) it adds the various "required" css classes but not the "required" attribute.

On the other hand, when I add the "required" to a string input which is not required by the model, it gets validated ok with html5.

Here's an example:

class Organization < ActiveRecord::Base
  //...
  validates_presence_of :name
  belongs_to :country
end
Then: 
    <%= simple_form_for @organization, :html => { :multipart => true } do |f| %>
         <p> Required by model, works with html5: </p>
         <%= f.input :name %>   
         <p> Required overridden, works with html5: </p>
         <%= f.input :postal_code, :required => true %>
         <p> Required doesn't render "required" in tag: </p>
         <%= f.input :country_id,  :collection => Country.all_sorted.map {|c| [c.name, c.id]}, :prompt => "- Select a Country -", :required => true %>
    <% end %>

Thanks!

-Mike

@rafaelfranca
Collaborator

I see. We disabled the required attribute for select fields based on the issue #141 as you can see in this line.

I saw the HTML 5 specification and I investigating if the require attribute can be used for select inputs.

Thanks for report the issue.

@rafaelfranca rafaelfranca reopened this Oct 17, 2011
@mikebridge

Sorry, I missed the discussion on issue #141. Yes, I think W3 added it to the spec about a year ago (20101019):

http://dev.w3.org/html5/spec-author-view/the-select-element.html#attr-select-required

Not sure what the status of browser support is for it, though.

Cheers!

-Mike

@rafaelfranca
Collaborator

I tried some snippets on the w3c validator it seems like the required attribute is only valid when the select has a blank option. So I think that we need to check only if the option :include_blank is not false or the :prompt option is present on the has_required? method of CollectionInput.

I will fix it when I have time.

@mskraddoc

Nice. Thanks!

@ndbroadbent

Can we also please disable the required attribute for the check_boxes collection?
Here is the exact issue that we are experiencing: http://stackoverflow.com/questions/5884582/hml5-required-attribute-on-multiple-checkboxes-with-the-same-name

In current browsers, all of the checkboxes must be selected in order to pass validation. That doesn't make sense - even if all the checkboxes have the required attribute, they should pass validation if one or more checkboxes with the same name are selected.

w3.org doesn't seem to want to change this broken behaviour... so can we please remove the required attribute?

@rafaelfranca
Collaborator

Ok. We can do this too. For now we can disable the browser_validations option

@nashby nashby added a commit to nashby/simple_form that referenced this issue Dec 1, 2011
@nashby nashby select can have required option, closes #340 2069b30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment