I have an index page that builds a table, and I am trying to allow users to edit line's in the table. I am trying to do this in the most basic way possible - no javascript, ajax, etc, unless Rails is supplying it.
I have my table displaying fine in the index method, and there is a form as the last row in the table that can be used to add a new row. The new form works fine. Each row has an edit link that routes to the controller's edit method. The controller sets the object to be edited, and renders index, this time with a form in the row that is to be edited. My problem is that this form will not submit, but if I refresh the page it will submit.
The fact that the page will submit after a refresh is very confusing. I don't see how a refresh would do anything different then clicking the link (it should still go through the same routing, with the same variables right?) and I can't see any difference in the form html before and after the refresh. Any have ideas on what might be happening?
I am not sure what code to even start looking in, but here goes;
index.html.erb
... <tbody> <% @boms.each do |line| %> <% if line == @bom %> <%= render("form_in_table", form_objects: @bom , button_text: "Update") %> <% else %> <%= render("bom_in_table", line: line) %> <% end %> <% end %> <% if @bom.new_record? %> <%= render("form_in_table", form_objects: [@li, @bom] , button_text: "Add") %> <% end %> </tbody> ...
_form_in_table.html.erb
<%= form_for(form_objects, html: {class: "form-in-table"}) do |f| %> <tr> <td><%= f.text_field :quantity %></td> <td colspan="2"> <%= f.select(:part_id, options_from_collection_for_select(@parts, :id, :pricebook_name), prompt: "Select a Part",) %></td> <td></td> <td></td> <td></td> <td><%= f.submit(button_text, class: "btn btn-primary btn-mini") %></td> </tr> <% end %>
_bom_in_table.html.erb
<tr> <td><%= line.quantity%></td> <td><%= line.part_number %></td> <td><%= line.part_description %></td> <td><%= number_to_currency(line.part_cost) %></td> <td><%= line.part_unit %></td> <td><%= number_to_currency(line.extension) %></td> <td><%= link_to('Edit', edit_bom_path(line)) %></td> </tr>
boms_controller.rb
... def edit @bom = Bom.find(params[:id]) @li = @bom.line_item @boms = @li.boms.sorted_by_part_number @parts = Part.sorted_by_number render 'index' end ...
In case this is useful to deciphering the code/intent, I have collections of line_items, parts, and boms; line_item has many boms, and line_item has many parts through boms. In addition to the part/line item relationship, boms have a quantity. Bom is short for bill of materials. @li is the line_item that is being manipulated. The form I having trouble with is for viewing/adding/editing the collection of boms (quantitys and parts) that belong to a line item.
ADDING LOGS
Started GET "/line_items/8/boms" for 127.0.0.1 at 2013-10-14 14:27:27 -0400 Processing by BomsController#index as HTML Parameters: {"line_item_id"=>"8"} [1m[35mLineItem Load (0.0ms)[0m SELECT "line_items".* FROM "line_items" WHERE "line_items"."id" = ? LIMIT 1 [["id", "8"]] [1m[36mLineItemSubClass Load (1.0ms)[0m [1mSELECT "line_item_sub_classes".* FROM "line_item_sub_classes" WHERE "line_item_sub_classes"."id" = ? ORDER BY "line_item_sub_classes"."id" ASC LIMIT 1[0m [["id", 8]] [1m[35mLineItemClass Load (4.0ms)[0m SELECT "line_item_classes".* FROM "line_item_classes" WHERE "line_item_classes"."id" = ? ORDER BY "line_item_classes"."id" ASC LIMIT 1 [["id", 1]] Rendered shared/_error_messages.html.erb (3.0ms) [1m[36mBom Load (1.0ms)[0m [1mSELECT "boms".* FROM "boms" INNER JOIN "parts" ON "parts"."id" = "boms"."part_id" WHERE "boms"."line_item_id" = ? ORDER BY "parts".number ASC[0m [["line_item_id", 8]] [1m[35mPart Load (0.0ms)[0m SELECT "parts".* FROM "parts" WHERE "parts"."id" = ? ORDER BY "parts"."id" ASC LIMIT 1 [["id", 1]] Rendered boms/_bom_in_table.html.erb (96.0ms) [1m[36mPart Load (1.0ms)[0m [1mSELECT "parts".* FROM "parts" ORDER BY "parts".number ASC[0m Rendered boms/_form_in_table.html.erb (103.0ms) [1m[35m (24.0ms)[0m SELECT SUM(quantity * cost) AS sum_id FROM "parts" INNER JOIN "boms" ON "boms"."part_id" = "parts"."id" WHERE "boms"."line_item_id" = 8 Rendered boms/index.html.erb within layouts/boms (477.0ms) Rendered layouts/_shim.html.erb (1.0ms) Rendered layouts/_header.html.erb (0.0ms) Rendered layouts/_footer.html.erb (0.0ms) Rendered layouts/application.html.erb (69.0ms) Completed 200 OK in 671ms (Views: 601.0ms | ActiveRecord: 31.0ms) Started GET "/boms/22/edit" for 127.0.0.1 at 2013-10-14 14:28:13 -0400 Processing by BomsController#edit as HTML Parameters: {"id"=>"22"} [1m[36mBom Load (0.0ms)[0m [1mSELECT "boms".* FROM "boms" WHERE "boms"."id" = ? LIMIT 1[0m [["id", "22"]] [1m[35mLineItem Load (1.0ms)[0m SELECT "line_items".* FROM "line_items" WHERE "line_items"."id" = ? ORDER BY "line_items"."id" ASC LIMIT 1 [["id", 8]] [1m[36mLineItemSubClass Load (1.0ms)[0m [1mSELECT "line_item_sub_classes".* FROM "line_item_sub_classes" WHERE "line_item_sub_classes"."id" = ? ORDER BY "line_item_sub_classes"."id" ASC LIMIT 1[0m [["id", 8]] [1m[35mLineItemClass Load (0.0ms)[0m SELECT "line_item_classes".* FROM "line_item_classes" WHERE "line_item_classes"."id" = ? ORDER BY "line_item_classes"."id" ASC LIMIT 1 [["id", 1]] Rendered shared/_error_messages.html.erb (0.0ms) [1m[36mBom Load (1.0ms)[0m [1mSELECT "boms".* FROM "boms" INNER JOIN "parts" ON "parts"."id" = "boms"."part_id" WHERE "boms"."line_item_id" = ? ORDER BY "parts".number ASC[0m [["line_item_id", 8]] [1m[35mPart Load (0.0ms)[0m SELECT "parts".* FROM "parts" ORDER BY "parts".number ASC Rendered boms/_form_in_table.html.erb (25.0ms) [1m[36m (0.0ms)[0m [1mSELECT SUM(quantity * cost) AS sum_id FROM "parts" INNER JOIN "boms" ON "boms"."part_id" = "parts"."id" WHERE "boms"."line_item_id" = 8[0m Rendered boms/index.html.erb within layouts/boms (41.0ms) Rendered layouts/_shim.html.erb (0.0ms) Rendered layouts/_header.html.erb (1.0ms) Rendered layouts/_footer.html.erb (0.0ms) Rendered layouts/application.html.erb (54.0ms) Completed 200 OK in 113ms (Views: 104.0ms | ActiveRecord: 3.0ms) Started GET "/boms/22/edit" for 127.0.0.1 at 2013-10-14 14:28:37 -0400 Processing by BomsController#edit as HTML Parameters: {"id"=>"22"} [1m[35mBom Load (0.0ms)[0m SELECT "boms".* FROM "boms" WHERE "boms"."id" = ? LIMIT 1 [["id", "22"]] [1m[36mLineItem Load (0.0ms)[0m [1mSELECT "line_items".* FROM "line_items" WHERE "line_items"."id" = ? ORDER BY "line_items"."id" ASC LIMIT 1[0m [["id", 8]] [1m[35mLineItemSubClass Load (0.0ms)[0m SELECT "line_item_sub_classes".* FROM "line_item_sub_classes" WHERE "line_item_sub_classes"."id" = ? ORDER BY "line_item_sub_classes"."id" ASC LIMIT 1 [["id", 8]] [1m[36mLineItemClass Load (1.0ms)[0m [1mSELECT "line_item_classes".* FROM "line_item_classes" WHERE "line_item_classes"."id" = ? ORDER BY "line_item_classes"."id" ASC LIMIT 1[0m [["id", 1]] Rendered shared/_error_messages.html.erb (0.0ms) [1m[35mBom Load (1.0ms)[0m SELECT "boms".* FROM "boms" INNER JOIN "parts" ON "parts"."id" = "boms"."part_id" WHERE "boms"."line_item_id" = ? ORDER BY "parts".number ASC [["line_item_id", 8]] [1m[36mPart Load (0.0ms)[0m [1mSELECT "parts".* FROM "parts" ORDER BY "parts".number ASC[0m Rendered boms/_form_in_table.html.erb (5.0ms) [1m[35m (0.0ms)[0m SELECT SUM(quantity * cost) AS sum_id FROM "parts" INNER JOIN "boms" ON "boms"."part_id" = "parts"."id" WHERE "boms"."line_item_id" = 8 Rendered boms/index.html.erb within layouts/boms (27.0ms) Rendered layouts/_shim.html.erb (1.0ms) Rendered layouts/_header.html.erb (8.0ms) Rendered layouts/_footer.html.erb (0.0ms) Rendered layouts/application.html.erb (60.0ms) Completed 200 OK in 131ms (Views: 94.0ms | ActiveRecord: 2.0ms) Started GET "/assets/application.css?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400 Started GET "/assets/custom.css?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400 Started GET "/assets/jquery.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400 Started GET "/assets/jquery_ujs.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400 Started GET "/assets/bootstrap-transition.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400 Started GET "/assets/bootstrap-affix.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400 Started GET "/assets/bootstrap-alert.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400 Started GET "/assets/bootstrap-collapse.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400 Started GET "/assets/bootstrap-modal.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:38 -0400 Started GET "/assets/bootstrap-carousel.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/bootstrap-button.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/bootstrap-dropdown.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/bootstrap-scrollspy.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/bootstrap-tab.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/bootstrap-typeahead.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/bootstrap-tooltip.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/bootstrap-popover.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/bootstrap.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/turbolinks.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/parts.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400 Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2013-10-14 14:28:39 -0400
Sometimes the problem is caused by old versions of the Javascript files, cached by your browser and can be fixed by clearing the browser cache. You can use the browser console of your browser for debugging. After the Javascript error is fixed, the submit button will automatically be enabled.
Enter = SubmitIf you have focus in the textbox and hit enter, the form will be submitted automatically. This behavior is consistent across all browsers and is known as implicit submission.
onsubmit = function () { if (allowSubmit) allowSubmit = false; else return false; } })(); (well, as sure-fire as you can get with JS enabled anyway). You could disabled the button as a visual confirmation to the end user that the form can only be submit once too. Very correct.
I believe this is an HTML issue, not a Rails issue. Per this discussion Form inside a table, <form>
can not be placed inside <table>
or <tbody>
or <tr>
. After moving the <form>
to wrap the table and putting the controls inside the respective <td>
the form works.
I still don't understand why refreshing the page made the form work, but...
If it's Rails 4, it's probably because of Turbolinks. Try putting
data-no-turbolink="true" inside your body tag
This may work, it happend once to me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With