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