【问题标题】:Form Submit button only works after reload表单提交按钮仅在重新加载后有效
【发布时间】:2013-10-14 17:30:34
【问题描述】:

我有一个构建表格的索引页面,我试图允许用户编辑表格中的行。我试图以最基本的方式做到这一点 - 没有 javascript、ajax 等,除非 Rails 提供它。

我的表格在 index 方法中显示良好,并且表格中的最后一行有一个表格,可用于添加新行。新表格工作正常。每行都有一个编辑链接,该链接路由到控制器的编辑方法。控制器设置要编辑的对象,并呈现索引,这次在要编辑的行中有一个表单。我的问题是这个表单不会提交,但是如果我刷新页面它会提交。

页面将在刷新后提交的事实非常令人困惑。我看不出刷新与单击链接有何不同(它仍应通过相同的路由,具有相同的变量对吗?),并且在刷新之前和之后我看不到 html 表单的任何差异.有人对可能发生的事情有想法吗?

我什至不确定要开始查找什么代码,但这里是;

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
...

如果这对破译代码/意图有用,我有 line_items、parts 和 boms 的集合; line_item 有很多 bom,line_item 通过 boms 有很多部分。除了零件/行项目关系之外,物料清单还有数量。 Bom 是物料清单的缩写。 @li 是被操纵的 line_item。我遇到问题的表单是用于查看/添加/编辑属于订单项的物料(数量和零件)集合。

添加日志

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

【问题讨论】:

  • 我没有看到任何可以让 Rails 像你说的那样表现的东西。你能添加一些日志吗?
  • 同上 - 很高兴看到一些日志。您可以从 /log/development.log 文件中获取它们 :)
  • 日志已添加到问题中。请注意,我在刷新之前多次点击提交按钮,但它没有创建任何日志条目。我确实注意到刷新获取了原始加载没有的几个资产。是这个问题吗?
  • 额外的 GET 是红鲱鱼。我得到了可以工作的表格(见下文),工作版本也没有得到这些资产。

标签: ruby-on-rails ruby-on-rails-4


【解决方案1】:

我相信这是一个 HTML 问题,而不是 Rails 问题。根据本次讨论,Form inside a table&lt;form&gt; 不能放在 &lt;table&gt;&lt;tbody&gt;&lt;tr&gt; 内。在移动 &lt;form&gt; 以包裹表格并将控件放入相应的 &lt;td&gt; 后,表单将起作用。

我仍然不明白为什么刷新页面会使表单工作,但是...

【讨论】:

  • 你能解释一下把控件放在中的原因吗
  • 起初以为是 turbolink 问题,但后来发现我在表格中使用了表单标签。
  • 在找到您的答案之前,我为此工作了两个小时。尝试了 turbolink 修复,添加了 javascript 来推送提交按钮等。
  • 确保 html 标签正确关闭并遵循 html 指南
  • 它是错误标记和 Turbolinks 的组合——对我来说是在 中嵌套一个表单。重新加载成功了,这绝对是由于 Turbolinks 不能很好地处理坏标记
【解决方案2】:

如果是 Rails 4,可能是因为 Turbolinks。 试试放

data-no-turbolink="true" inside your body tag

这可能有效,它发生在我身上一次。

【讨论】:

  • 花了三个小时寻找这个解决方案。谢谢你。
  • 这不是解决方案,这是一个补丁,您正在禁用 Turbolinks :/ 虽然这是一个有效的决定,但这不是问题的解决方案。 Garret 和 Jerome 的答案更好。
【解决方案3】:

这种类型的错误最常由无效的 HTML 生成。各种错误来源可能是:

  • 缺少&lt;&gt;
  • HTML 标记未关闭
  • 孤立的 HTML 结束标签(没有相关的开始标签);在复杂的形式中,我有额外的&lt;/div&gt;s 撒谎...
  • 嵌套在tabletr 标记内的表单(允许在td 内)

表单助手需要正确嵌套,否则这些怪癖会咬你...

【讨论】:

  • 太棒了……这对我有用。我有一个流浪的
    ,我通过逐步删除表单中的输入直到它起作用来捕获它,以隔离问题。
【解决方案4】:

尝试将 data-no-turbolink="true" 放入调用表格页面的链接中。

 <a href="/vender" data-no-turbolink="true">

这对我有用。

【讨论】:

    【解决方案5】:

    对于 rails 5,尝试在指向包含表单的页面的任何链接中使用 data: { turbolinks: false }

    例如&lt;%= link_to "Get in Touch", 'contact', data: { turbolinks: false } %&gt;

    【讨论】:

    • 对于那些别无选择只能在表格中使用表格的人的最佳答案。这是唯一一个对我有用的,它允许 turbolinks 在其他地方工作(当然没有 turbolinks 的 if 语句)
    • 我在展示页面上显示了一个表单,并且使用索引页面上的链接中的 data: { turbolinks: false } 允许我在不刷新页面的情况下提交表单。谢谢。
    【解决方案6】:

    我必须分享我的经验: 我和你一样玩过 Turbolinks。但突然间,我遇到了一个问题:之前的页面也需要禁用 turbolinks 才能正常工作。 在这个问题上很多很多小时后,我找到了解决方案: &lt;% f.submit %&gt; 被 2 &lt;div&gt; 与表格的其余部分隔开! 这是一个例子: 错误:

    <div class="container">
        <div class="row">
            <!-- Inscription -->
            <div class="col-lg-8 contact_col">
                <div class="get_in_touch">
                    <div class="section_title">Modifier une marque</div>
                    <div class="contact_form_container">
                        <%= form_for @brand, url: {action: "update"} do |f| %>
                        <div class="row">
                            <div class="col-xl-12">
                                <!-- Name -->
                                <label for="contact_name">Nom de la marque</label>
                                <%= f.text_field :brand, class: "contact_input" %>
                            </div>
                            <div class="col-xl-12 last_name_col">
                                <span>
                                    <%= f.label "Image de la marque" %><br />
                                </span>
                                <%= f.file_field :brand_picture %>
                            </div>
                        </div>
                    </div>
                </div>
                <button class="newsletter_button trans_200">
                    <%= f.submit "Modifier" %>
                </button>
                <% end %>
            </div>
        </div>
    </div>
    

    正确:

       <div class="container">
        <div class="row">
            <!-- Inscription -->
            <div class="col-lg-8 contact_col">
                <div class="get_in_touch">
                    <div class="section_title">Modifier une marque</div>
                    <div class="contact_form_container">
                        <%= form_for @brand, url: {action: "update"} do |f| %>
                        <div class="row">
                            <div class="col-xl-12">
                                <!-- Name -->
                                <label for="contact_name">Nom de la marque</label>
                                <%= f.text_field :brand, class: "contact_input" %>
                            </div>
                            <div class="col-xl-12 last_name_col">
                                <span>
                                    <%= f.label "Image de la marque" %><br />
                                </span>
                                <%= f.file_field :brand_picture %>
                            </div>
                        </div>
                        <button class="newsletter_button trans_200">
                            <%= f.submit "Modifier" %>
                        </button>
                        <% end %>
                    </div>
                </div>
            </div>
        </div>
    </div>
    

    【讨论】:

      【解决方案7】:

      认为您的解决方法可能是在提交表单时重新加载。所以将remote: true 添加到您的表单中。这只会为您快速刷新。请注意,这不是解决方案,而是解决方法。推荐的解决方案是 Garrett Berneche 的回答。

      <%= form_for(form_objects, html: {class: "form-in-table"}, remote: true) do |f| %>
      

      【讨论】:

        猜你喜欢
        相关资源
        最近更新 更多
        热门标签