Rails does not add "field_with_errors' wrapper for fields created with fields_for

359 views Asked by At

What I am trying to do is namespace a custom-made object in a dyamically-built form by passing it to fields_for. The object is not an ActiveRecord model and I am doing my best to make it quack like one with minimal effort.

Everything works with the exception of the "field_with_errors" wrapper which does not get added. Any ideas on how to make that part work?

I have a form which submits data to FormResponses model and runs its validations. Once the validations are run, the form_response object contains the namespaced form data as well as errors:

[1] pry(#<#<Class:0x007fe743c64418>>)> form_response
=> #<FormResponse:0x007fe74d30aa98
 id: nil,
 data: {"name_prefix"=>"Mr.", "first_name"=>"", "middle_initial"=>"", "last_name"=>"", "name_suffix"=>"", "title"=>""},
 form_id: 2,
 created_at: nil,
 updated_at: nil>

[2] pry(#<#<Class:0x007fe743c64418>>)> form_response.errors
=> #<ActiveModel::Errors:0x007fe74d309080
 @base=
  #<FormResponse:0x007fe74d30aa98
   id: nil,
   data: {"name_prefix"=>"Mr.", "first_name"=>"", "middle_initial"=>"", "last_name"=>"", "name_suffix"=>"", "title"=>""},
   form_id: 2,
   created_at: nil,
   updated_at: nil>,
 @messages={:will_attend=>["Please indicate your attendance"], :first_name=>["Please provide your first name"]}>

# this is what I pass to the form_for builder
[3] pry(#<#<Class:0x007fe743c64418>>)> form_response.form_data
=> #<OpenStruct name_prefix="Mr.", first_name="", middle_initial="", last_name="", name_suffix="", title="">

I display this object in the following way:

form.html.slim

= form_for form_response, url: "", authenticity_token: false, html: {class: "form"} do |ff|
  = hidden_field_tag "authenticity_token", csrf_token
  = ff.hidden_field "_prefilled_status", value: is_prefilled.prefilled
  = ff.hidden_field "_prefilled_condition", value: is_prefilled.condition

  = fields_for :form_data, form_response.form_data do |f|
    = ff.hidden_field "form_id", value:  form_response.form_id
    # form_components holds the form field tree data which lets us create the form dynamically
    - form_components.each do |component|      
      = render partial: "./#{component.kind}", locals: { f: f, component: component }

having each of the fields processed by a partial corresponding to the field type, for example:

_text.html.slim

li class=component.container_css
  = f.label component.field_name, component.label, class: concat_and_trim('desc', component.required_class)
  span = f.text_field component.field_name, component.tag_options_with_css

The issue is that the fields created with f.field_name do not get the "field_with_errors" wrapper when errors are present.

Given that the errors are on the form_response active record model passed on to the "ff" form builder, shouldn't they trigger the wrapping on the form_for objects?

The form_for fields retainthe submitted values if I include form_response.form_data which contains the form field values submitted under the form_data namespace, like this:

  = fields_for :form_data, form_response.form_data do |f| 

If I omit the form_response.form_data part, the fields get cleared on submit

  = fields_for :form_data do |f|

Which means that the fields_for uses that information to prefill the fields. How do I pass the error information to fields_for so that the fields get the error class wrapper?

0

There are 0 answers