Rails 动态生成的 fields_for 不会被 form_tag 作为输入

Posted

技术标签:

【中文标题】Rails 动态生成的 fields_for 不会被 form_tag 作为输入【英文标题】:Rails dynamically generated fields_for are not picked up as inputs by form_tag 【发布时间】:2020-07-30 12:59:04 【问题描述】:

我正在尝试以一种形式创建多个对象。不是父子关系的东西,对象都是一样的。

当代码如下所示时,它工作得很好。

<%= form_tag create_object_path, id: "create-object-form" do %>
  <%= render "admins/object_fields" %>
  <!-- repeat render any number of times -->
<% end %>

# where the render looks like this:
<%= fields_for "objects[]" do |f| %>
  <tr class="new-object">
    <td><%= f.text_field :name %></td>
  </tr>
<% end %>

一种测试方法是,在控制台中,$("#create-object-form").serializeArray() 根据已呈现的object_fields 的数量正确返回输入字段的数量。

但是,当动态调用渲染时,动态添加的fields_for 不会出现在提交中。并且调用$("#create-object-form").serializeArray() 只返回2 个字段,utf8authenticity_tokenform_tag 自动生成。无法运行的代码

<%= form_tag create_object_path, id: "create-object-form" do %>
  <!-- render called by JS -->
<% end %>

<button id="add-object">Add</button>

$("#add-object").click(function() 
  $.ajax()...
  // correctly fetches and renders the partial on the page in the correct spot.
)

# where the render STILL looks like this, no change:
<%= fields_for "objects[]" do |f| %>
  <tr class="new-object">
    <td><%= f.text_field :name %></td>
  </tr>
<% end %>

【问题讨论】:

在 Rack 中,您无法通过数组参数可靠地传递哈希数组。举个例子:objects[][foo]="bar"&amp;objects[][id]="1"&amp;objects[][foo]="baz"&amp;objects[][id]="2"。 Rack 无法知道每个值属于什么哈希值。相反,您需要传递一个哈希值:objects[0][foo]="bar"&amp;objects[0][id]="1"&amp;objects[1][foo]="baz"&amp;objects[1][id]="2". 如果您将数组或任何可枚举对象传递给 fields_for,它实际上会遍历集合并正确设置。 @max 我有点困惑,你的第一条评论表明问题在于通过哈希传递数组(即使我的程序可以很好地传递一个数组,只要有多个对象,只要因为它们不是动态呈现的),但是您的第二条评论表明数组可以吗?我不完全确定您建议的解决方案是什么,抱歉! 第一条评论是关于rack如何解释表单数据参数,当你传递fields_for "objects[]"时,你将构造Rack无法处理的参数。 我对这个问题提出的解决方案是不要这样做。如果您使用 Ajax 并逐个添加记录,则可以为每条记录只使用一个表单 - 它的复杂性和hacky要少得多。 【参考方案1】:

答案很有趣。不明白为什么,也没有做大量的实验,欢迎大家进一步补充。

问题缺少一些上下文。输入在表格中的行中,因此代码实际上如下所示:

<table>
  <thead>...content...</thead>
  <%= form_tag form_path, id: "form" do %>
    <tbody>
      <!-- either pre-rendered or dynamically generated trs with input fields -->
    </tbody>
    <tbody>
      <tr>
        <td colspan="3">
          <button id="submit">Submit</button>
        </td>
      </tr>
    </tbody>
  <% end %>
</table>

form_tag 包裹在 tbody 周围,其中包含 trsinput 字段。在该版本的代码中,仅在提交时或.serializeArray() 提取了预渲染的输入,如问题所述。

但是,如果我将form_tag 移动到table 标记之外,那么它可以工作;即,动态添加的trsinput 字段在提交时或由.serializeArray() 成功提取。

同样,我不知道为什么,找不到任何表明这是预期行为的文档,所以请随时告诉我。谢谢!

工作代码:

<%= form_tag form_path, id: "form" do %>
  <table>
    <thead>...content...</thead>
    <tbody>
      <!-- either pre-rendered or dynamically generated trs with input fields -->
    </tbody>
    <tbody>
      <tr>
        <td colspan="3">
          <button id="submit">Submit</button>
        </td>
      </tr>
    </tbody>
  </table>
<% end %>

【讨论】:

以上是关于Rails 动态生成的 fields_for 不会被 form_tag 作为输入的主要内容,如果未能解决你的问题,请参考以下文章

Rails,fields_for,合并记录

Rails 设计 fields_for 不工作

Rails:使用 fields_for 和 check_box

ruby 使用Rails中的fields_for编辑表单

Rails 动态渲染局部

Rails fields_for 表单未显示,嵌套表单