nested_form_fields icon indicating copy to clipboard operation
nested_form_fields copied to clipboard

nested_form.object.parent.attribute doesn't work for some parents

Open bassman88 opened this issue 7 years ago • 10 comments

In the code below, ff.object.product.name works but ff.object.sales_order_item and ff.object.delivery doesn't. They all have the same associations in the model. belongs to and has_many, optional: true.

If I change to form.fields_for, all the values are displayed. Is there something going on under the hood that disables getting object.parent.attribute for some parents?

<%= form.nested_fields_for :delivery_items, wrapper_tag: :tr do |ff| %>
  <td class="col-md-1">
    <div class="input-product_code-div">
        <%= ff.object.product.name  %> <br>
        <%= ff.object.sales_order_item.address  %> <br>
        <%= ff.object.delivery.id  %>
        <%end%>
    </div>
  </td>
<% end %>

bassman88 avatar Nov 02 '17 07:11 bassman88

That is odd. Is the main form object already saved in the db? Curious, can you try ff.object.reload.sales_order_item? Does that work? Seems ff.object is not initialized properly.

ncri avatar Nov 04 '17 21:11 ncri

I tried your suggestion, it still doesn't work but now produces a different error: Couldn't find DeliveryItem without an ID

My current workaround is to simply use rails' standard fields_for and everything works as expected.

bassman88 avatar Nov 05 '17 09:11 bassman88

Ah, so ff.object.reload.delivery produces this? Is delivery a belongs_to association? If so what does ff.object.delivery_id return?

ncri avatar Nov 05 '17 11:11 ncri

delivery items belongs_to delivery. delivery has_many delivery_items. ff.object.delivery_id outputs the integer that connects delivery_items to delivery.

bassman88 avatar Nov 06 '17 02:11 bassman88

Okay, so ff.object.delivery returns nil, even though the id is in ff.object.delivery_id. The easy workaround then is to do delivery = Delivery.find ff.object.delivery_id. What is the object of the main form? Can you post the whole form here?

ncri avatar Nov 06 '17 07:11 ncri

The main form object is @delivery. I tried doing the "find" workaround but that doesnt work, it suddenly doesn't detect the delivery_id anymore. Here is the whole form, where I used form_for instead, this works:

<%= form_with(model: delivery, local: true) do |form| %> <% if delivery.errors.any? %>

<%= pluralize(delivery.errors.count, "error") %> prohibited this delivery from being saved:

  <ul>
  <% delivery.errors.full_messages.each do |message| %>
    <li><%= message %></li>
  <% end %>
  </ul>
</div>

<% end %>

  <!-- Text input-->
  <div class="form-group">
    <label class="col-md-4 control-label" for="textinput">Delivery Date</label>  
    <div class="col-md-2">
      <div class="form-group input-group">   
        <div class="input-group-addon">
          <span class="glyphicon glyphicon-calendar"></span>
        </div>                              
            <%= form.date_field :delivery_date, class: 'form-control input-md' %>
      </div>
    </div>
  </div>

  <div class="clearfix"></div>

  <!-- Text input-->
  <div class="form-group">
    <label class="col-md-4 control-label" for="textinput">Delivery Address</label>  
    <div class="col-md-8">
      <%= form.text_field :address, placeholder: "Delivery Address", class: "form-control input-md" %>
    </div>
  </div>

  <div class="clearfix"></div>
  <br>

  <!-- Text input-->
  <div class="form-group">
    <label class="col-md-4 control-label" for="textinput">Delivered? </label>  
    <div class="col-md-8">
       <%= form.check_box :is_delivered? %>
    </div>
  </div>

  <div class="clearfix"></div>
  <br>

  <div class="col-md-12">
    <h4>Delivery Items</h4>
    <div class="row">
        <div class="col-md-12">
            <div class="table-responsive" >
                <table class="table table-md preview-table">
                    <thead>
                        <tr>
                            <th class="col-md-3">Item Code</th>
                            <th>Item Name</th>
                            <th class="col-md-2">Quantity</th>
                        </tr>
                    </thead>
                      <tbody>
                            <%= form.fields_for :delivery_items do |ff| %>
                            <tr>
                              <td class="col-md-1">
                                <div class="input-product_code-div">
                                    <% if ff.object.product.present?  %>
                                      <%= ff.object.product.code %>
                                    <%else%>
                                      SERVICE
                                    <%end%>
                                </div>
                              </td>
                              <td>               
                                <div class="input-product_name-div">   
                                    <% if ff.object.product.present? %>
                                      <%= ff.object.product.name %>
                                    <%else%>
                                      <%= ff.object.sales_order_item.service_name %>
                                    <%end%>
                                </div>
                              </td>
                              <td class="col-md-1">
                                <%=  ff.number_field :quantity, :step => "0.01", max: ff.object.sales_order_item.unpurchased_quantity, class: "form-control input-quantity" %>        
                              </td>
                            </tr>
                          <% end %>
                      </tbody>
                </table>
            </div>                            
        </div>
    </div>

  <div class="form-group">
    <div class="col-md-12">
      <br>          
    </div>
  </div>

  </fieldset>
</div>
<%= form.submit(@delivery.new_record? ? 'Create Delivery Receipt' : 'Update Delivery Receipt', class: "btn btn-success pull-right") %>   

bassman88 avatar Nov 06 '17 07:11 bassman88

Thanks. You use the new form_with, not form_for. Does your form also work with form_for? And did you try that with nested_form_fields?

ncri avatar Nov 06 '17 07:11 ncri

Oh, and if the whole form is for delivery, there is no need to get the delivery inside the nested_form_fields - you have it already.

ncri avatar Nov 06 '17 07:11 ncri

I tried changing to form_for for delivery form and fields_for for delivery_items form. They work, but the moment I change delivery_items to nested_fields_for, it fails with the same error

bassman88 avatar Nov 06 '17 08:11 bassman88

Okay, so only issue really is ff.object.sales_order_item that could be grabbed by doing:

sales_order_item = SalesOrderItem.find ff.object.sales_order_item_id if ff.object.sales_order_item_id

Easy workaround, but I understand it still is a workaround. Need to dig deeper into the code to find out what is going on.

ncri avatar Nov 06 '17 10:11 ncri