0

I'm working on a Rails (4.2.6) app, and have encountered an issue with one of my pages.

The page in question contains multiple forms, for various model attributes to assist with the generation of a product quote. For example, it allows you to set order specific details such as selling quantity, margin percentage and so on. Each field is an individual form, submitted via ajax, and re-rendering a number of partials on the page as a result. ( _costings.html.erb )

It also allows you to select product quotation quantities (and therefore the cost per unit) to include within the quote, from a table of nested forms (each form on one table row, and each with a checkbox). Upon checking / unchecking any of the boxes, it submits the relevant form via jQuery (remote: false). ( _factory_quotes.html.erb )

Upon initial load of the page, the product form submission works perfectly. I can check / uncheck as many boxes as I want and the data will be submitted correctly, and page refreshed.

The problem comes when I update any order value that is submitted via ajax and the partials are re-rendered (but page not fully refreshed). After that, the factory quotes form is submitted as a Post, rather than a Patch, rendering an error such as [No route matches [POST] "/quotation_quantities/83" ].

My assumption is that this is related to something not being refreshed / bound as it should be, after the ajax call, but I can't figure out the solution.

The product quotation quantity table body (_factory_quotes.html.erb):

<tbody>
    <% @related_quotes.each do |e| %>
        <tr id="<%= e.id %>" class="<%= if e.quantity == @order_costing.order_quantity then
                                                          'success'
                                                        elsif e.quantity > @order_costing.order_quantity then
                                                          'warning '
                                                        end %>">
            <%= form_for e, method: :put, html: {:id=> "form-#{e.id}"}, remote: false do |quote| %>                       
                <td>
                    <%= quote.object.quantity %>
                </td>
                <td>
                    <%= quote.object.production_lead_time %>
                </td>
                <td>
                    <%= Money.new(quote.object.unit_price*100, quote.object.ordercurrency.name).format unless quote.object.unit_price.nil? %>
                </td>
                <td>
                    <%= quote.check_box :use_in_costing %>
                </td>
                <% end %>
        </tr>
        <script>
            $(document).ready(function() {
                $('#<%= e.id %>').on('change', function() {
                    $("#form-<%= e.id %>").submit();
                });
            });
        </script>
        <% end %>
</tbody>

Example order specific details form (_costings.html.erb):

<div class="row" id="text3">
  <div id="text">
    <%= form_for @order_costing, remote: true do |f| %>
        <div class="col-xs-8">
          <%= f.label :gross_margin, 'Margin(%)' %>
        </div>
        <div class="col-xs-8" %>
          <div class=<%= @order_costing.gross_margin <= 20 ? "has-error" : "" %>>
            <%= f.number_field :gross_margin, class: 'form-control', :step => 'any' %>
          </div>
        </div>
        <div class="col-xs-4">
          <%= f.submit 'Apply', id: "box3", class: 'btn btn-sm btn-default', style: 'float:right' %>
        </div>
    <% end %>
  </div>
</div>

Update.js.erb:

$("#order_costings").html("<%= j render(partial: 'costings') %>");
$("#order_extras").html("<%= j render(partial: 'extras') %>");
$("#order_factory_quotes").html("<%= j render(partial: 'factory_quotes') %>");
$("#order_summary").html("<%= j render(partial: 'summary') %>");
$("#order_quote_quantities").html("<%= j render(partial: 'quote_quantities') %>");

order_costings_controller.html.erb

  def update
    respond_to do |format|
      if @order_costing.update(order_costing_params)
        #call a couple of helpers
        order_costing_calculations
        gather_selected_quote_data

        format.html
        format.js { render layout: false }
      end
    end
  end
AlainR
  • 1
  • 1
  • Rails doesn't actually use HTTP PATCH requests, but a `_method`-param in the form, with a POST-request. – Frederik Spang Sep 23 '16 at 09:16
  • OK, but it logs as a patch initially (before an ajax partial render): `Started PATCH "/quotation_quantities/82" for 127.0.0.1 at 2016-09-23 11:03:08 +0100` But a Post after the partial has been rendered by ajax: `Started POST "/quotation_quantities/83" for 127.0.0.1 at 2016-09-23 11:04:10 +0100` Despite `` but present in both scenarios. – AlainR Sep 23 '16 at 10:05

1 Answers1

0

It turns out this is the result of the form being a child element of the table. It is easily resolved by moving the form to within the table cell <td>. sigh

I found this out from the following thread: Form inside a table

Community
  • 1
  • 1
AlainR
  • 1
  • 1