【问题标题】:Form Inputs Within Elixir List ComprehensionElixir 列表理解中的表单输入
【发布时间】:2017-02-16 03:59:56
【问题描述】:

我正在显示一个学生表,并希望每一行都有一个表单元素,可用于更改有关该学生的信息。我目前拥有的(如下所示)仅适用于表中的最后一个学生,因为它看起来 :manual_choice:student_id 不是逐行唯一的表单字段。

如何让所有学生的列表理解为表格的每一行生成唯一的表单字段,以便在我提交表单时,我可以更新为他们选择了 manual_choice 的学生?

<%= form_for @changeset, assignments_path(@conn, :manual_assign), fn f -> %>
<table id="students" class="display" cellspacing="0" width="100%">
  <thead>
    <tr>
      <th>Student Name</th>
      <th>Assigned Project</th>
      <th>Override Assignment</th>
    </tr>
  </thead>
  <tbody>
    <%= for student <- @all_students do %>
      <tr>
        <td><%= student.student_name %></td>
        <td><%= student.assigned_project %></td>
        <td class="text-right">
          <div class="form-group">
              <%= select f, :manual_choice, @projects, class: "form-control", id: "manual_choice" %>
              <%= text_input f, :student_id, class: "form-control", value: student.id, style: "display:none" %>
          </div>
        </td>
      </tr>
    <% end %>
  </tbody>
</table>
<% end %>

【问题讨论】:

  • 为什么不把form_for 放在2 个输入(select 和text_input)周围?页面上可以有多个表单,提交一个只会提交该表单的值。
  • 这可行。然后我需要为每一行提供一个提交按钮,对吗?
  • 是的。您希望能够同时更改多个学生吗?

标签: forms elixir phoenix-framework


【解决方案1】:

正如受人尊敬的 Dogbert 指出的那样,也许一种维护成本较低的方法是为每个学生记录创建一个单独的表单;单击提交按钮将仅提交该记录的数据。

但是,如果您特别想要一张底部有一个提交按钮的巨型表格(更适合一些批量更新的情况),也许您可​​以在每个输入的名称中包含一个递增的计数器。一个简单的示例可能如下所示:

<%= @all_students |> Enum.with_index |> Enum.each(fn(student, index) -> %>
  ...
    <%= select f, "student_#{index}[manual_choice]", @projects, class: "form-control" %>
    <%= text_input f, "student_#{index}[id]", value: student.id, style: "display:none" %>
  ...
<% end %>

注意事项:

  1. 我使用Enum.with_indexEnum.each 来遍历学生列表,而不是for student &lt;- @students。我来自 Ruby 世界,在那里 for 循环不受欢迎;我发现我总是可以使用Enum.eachEnum.map,我还不需要使用for 构造。
  2. 对于选择和输入元素,我提供了一个对每个元素都是唯一的字符串。例如第五行的选择名称应该是student_4[manual_choice]
  3. 我还没有测试过这一切;我只是在吐口水。我相信这种通用方法会很好地工作,但不清楚确切的语义。例如,我不知道Enum.each 是否真的会打印出任何生成的标记/内容; Enum.map 可能会更好。
  4. 接收提交表单的控制器端点必须能够理解参数并遍历每个学生的表单数据。我怀疑这很容易(在 Rails 世界中非常容易),但在 Elixir/Phoenix 中还没有这样做。

如果 #4 给您带来麻烦,也许更简单的方法是使用数组语法命名每个输入元素,例如:"students[manual_choice][]""students[id][]"。这样,在控制器操作中,您可以遍历 students[id] 嵌套参数,并相信每个条目对应于 students[manual_choice] 的相同索引。

【讨论】: