自定义 inputs_for 表单输出的子索引
Customize child index of inputs_for form output
我正在尝试创建一个包含地址列表的表单,并允许用户通过 Javascript 删除或创建新地址。我使用 Rails' fields_for 和 child_index: 'new_record' 来实现类似的功能,在附加表单字段时我用时间戳替换了 new_record 字符串通过 Javascript(如本 Pluralsight 教程所述:https://www.pluralsight.com/guides/ruby-on-rails-nested-attributes)。
我正在寻找的技巧是在 Phoenix 中具有类似的呈现功能,即如何生成具有给定/自定义子索引的嵌套表单。目前我正在为这样的事情苦苦挣扎;
<%= form_for @changeset, Routes.user_path(@conn, :update, @user.id), [data: [controller: "nested-form", action: "nested-form#submit"]], fn f -> %>
<div data-target="nested-form.records">
<%= inputs_for f, :addresses, fn fp -> %>
<%= render __MODULE__, "_address_fields.html", form: fp %>
<% end %>
</div>
<template data-target="nested-form.template">
<%# How do I get a template input group here? %>
<%# In Rails I could do `f.fields_for :addresses, Address.new, child_index: 'NEW_RECORD'` %>
</template>
<% end %>
但我不知道如何使用 Phoenix 生成 inputs_for
来创建这样的模板。
正如@TheAnh 评论的那样,这个要点中讨论了答案 (https://gist.github.com/mjrode/c2939ee7786b157aab131761c8fb89a9)。为了提供答案,我使用以下辅助方法解决了它;
defmodule MyAppWeb.UserView do
use MyAppWeb, :view
def template_inputs_for(changeset, field, fun) do
form = Phoenix.HTML.FormData.to_form(changeset, [])
inputs_for(form, field, fn form ->
id = String.replace(form.id, ~r/\d$/, "NEW_RECORD")
name = String.replace(form.name, ~r/\[\d\]$/, "[NEW_RECORD]")
fun.(%{form | id: id, name: name})
end)
end
end
然后可用于生成“模板”字段组;
<%= form_for @changeset, Routes.user_path(@conn, :update, @user.id), [data: [controller: "nested-form", action: "nested-form#submit"]], fn f -> %>
<div data-target="nested-form.records">
<%= inputs_for f, :addresses, fn fp -> %>
<%= render __MODULE__, "_address_fields.html", form: fp %>
<% end %>
</div>
<template data-target="nested-form.template">
<%= template_inputs_for User.changeset(%User{addresses: [%Address{}]}), :addresses, fn f -> %>
<%= render __MODULE__, "_address_fields.html", form: f %>
<% end %>
</template>
<% end %>
我正在尝试创建一个包含地址列表的表单,并允许用户通过 Javascript 删除或创建新地址。我使用 Rails' fields_for 和 child_index: 'new_record' 来实现类似的功能,在附加表单字段时我用时间戳替换了 new_record 字符串通过 Javascript(如本 Pluralsight 教程所述:https://www.pluralsight.com/guides/ruby-on-rails-nested-attributes)。
我正在寻找的技巧是在 Phoenix 中具有类似的呈现功能,即如何生成具有给定/自定义子索引的嵌套表单。目前我正在为这样的事情苦苦挣扎;
<%= form_for @changeset, Routes.user_path(@conn, :update, @user.id), [data: [controller: "nested-form", action: "nested-form#submit"]], fn f -> %>
<div data-target="nested-form.records">
<%= inputs_for f, :addresses, fn fp -> %>
<%= render __MODULE__, "_address_fields.html", form: fp %>
<% end %>
</div>
<template data-target="nested-form.template">
<%# How do I get a template input group here? %>
<%# In Rails I could do `f.fields_for :addresses, Address.new, child_index: 'NEW_RECORD'` %>
</template>
<% end %>
但我不知道如何使用 Phoenix 生成 inputs_for
来创建这样的模板。
正如@TheAnh 评论的那样,这个要点中讨论了答案 (https://gist.github.com/mjrode/c2939ee7786b157aab131761c8fb89a9)。为了提供答案,我使用以下辅助方法解决了它;
defmodule MyAppWeb.UserView do
use MyAppWeb, :view
def template_inputs_for(changeset, field, fun) do
form = Phoenix.HTML.FormData.to_form(changeset, [])
inputs_for(form, field, fn form ->
id = String.replace(form.id, ~r/\d$/, "NEW_RECORD")
name = String.replace(form.name, ~r/\[\d\]$/, "[NEW_RECORD]")
fun.(%{form | id: id, name: name})
end)
end
end
然后可用于生成“模板”字段组;
<%= form_for @changeset, Routes.user_path(@conn, :update, @user.id), [data: [controller: "nested-form", action: "nested-form#submit"]], fn f -> %>
<div data-target="nested-form.records">
<%= inputs_for f, :addresses, fn fp -> %>
<%= render __MODULE__, "_address_fields.html", form: fp %>
<% end %>
</div>
<template data-target="nested-form.template">
<%= template_inputs_for User.changeset(%User{addresses: [%Address{}]}), :addresses, fn f -> %>
<%= render __MODULE__, "_address_fields.html", form: f %>
<% end %>
</template>
<% end %>