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 个字段,utf8
和authenticity_token
由form_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"&objects[][id]="1"&objects[][foo]="baz"&objects[][id]="2"
。 Rack 无法知道每个值属于什么哈希值。相反,您需要传递一个哈希值:objects[0][foo]="bar"&objects[0][id]="1"&objects[1][foo]="baz"&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
周围,其中包含 trs
和 input
字段。在该版本的代码中,仅在提交时或.serializeArray()
提取了预渲染的输入,如问题所述。
但是,如果我将form_tag
移动到table
标记之外,那么它可以工作;即,动态添加的trs
和input
字段在提交时或由.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 作为输入的主要内容,如果未能解决你的问题,请参考以下文章