自定义input_for表单输出的子索引

问题描述

我正在尝试创建带有地址列表的表单,并允许用户通过Javascript删除或创建新地址。我已将Rails的fields_for与child_index:'new_record'结合使用,以实现类似的功能,其中在通过JavaScript附加表单字段时,我用时间戳替换了new_record字符串(如本Pluralsight教程:https://www.pluralsight.com/guides/ruby-on-rails-nested-attributes所述)。 / p>

我正在寻找的技巧是在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,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{}]}),fn f -> %>
      <%= render __MODULE__,form: f %>
    <% end %>
  </template>
<% end %>