Phoenix LiveView 动态 select 标签表格问题

Phoenix LiveView dynamic select tags in form troubles

在带有 3 个 select 标签的 phoenix LiveView 表单中,第一个影响其他两个,即从属的两个应该只显示第一个可用的选项,如下所示:

<%= f = form_for @changeset, "#", id: "eval-form", phx_target: @myself, phx_change: "validate", phx_submit: "save" %>
  <%= select(f, :item1_id, Enum.map(@item1s, fn {_,v} -> {v.name, v.id} end), prompt: "Choose item1...") %>
  <% item1_id = @changeset |> Ecto.Changeset.get_field(:item1_id) %>
  <%= select(f, :item2_id, item1_id && Enum.map(@item1s[item1_id].item2s, &{&1.name, &1.id}) || []) %>
  <%= select(f, :item3_id, item1_id && Enum.map(@item1s[item1_id].item3s, &{&1.name, &1.id}) || []) %>
</form>

item1 被选择时,item2item3 select 标签确实包括正确的相应选项,但不显示任何选择的项目(因为它们不包括提示,第一个选项应该是 selected)。变更集不包括 item2item3 的变更(与显示的相匹配)。但是,在选择 item2 之后,item3 显示第一个选项(按预期)。在那之后,变更集确实包括 item1item2 更改,但是 item3 selected 选项不存在。

问题:

  1. 如何让相关的 select 标签(item2item3)在更改第一个 select(item1)?
  2. 如何从相关 select 标签中获取 'default' 选项到变更集中?

您是否尝试过对 select 标签使用 value 选项?像这样:

<%= item2_values = item1_id && Enum.map(@item1s[item1_id].item2s, &{&1.name, &1.id}) || [] %>
<%= select(f, :item2_id, item2_values, value: @changeset |> Ecto.Changeset.get_field(:item2_id, List.first(item2_values))) %>

但是,我认为您应该在 LiveView 模块中执行此逻辑。如果您的表单触发了一个 phx-change 事件,您实际上可以在干净的函数中将 item2_values 分配给套接字。

我用 'two phase changeset casting' 解决了这个问题。

在处理phx-change事件时,首先会转换并验证item1属性。接下来,根据需要更改 item2item3 属性(即项目值和选定值)。最后,item2item3 属性被强制转换和验证。

It seems that this also works for any dynamic forms (e.g. in my case when item1 is selected, items for item2 are set, when item2 is selected additional fields appear item2).

所需的

如果有更好的方法,我愿意接受建议。