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
被选择时,item2
和 item3
select 标签确实包括正确的相应选项,但不显示任何选择的项目(因为它们不包括提示,第一个选项应该是 selected)。变更集不包括 item2
和 item3
的变更(与显示的相匹配)。但是,在选择 item2
之后,item3
显示第一个选项(按预期)。在那之后,变更集确实包括 item1
和 item2
更改,但是 item3
selected 选项不存在。
问题:
- 如何让相关的 select 标签(
item2
和 item3
)在更改第一个 select(item1
)?
- 如何从相关 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
属性。接下来,根据需要更改 item2
和 item3
属性(即项目值和选定值)。最后,item2
和 item3
属性被强制转换和验证。
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
).
所需的
如果有更好的方法,我愿意接受建议。
在带有 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
被选择时,item2
和 item3
select 标签确实包括正确的相应选项,但不显示任何选择的项目(因为它们不包括提示,第一个选项应该是 selected)。变更集不包括 item2
和 item3
的变更(与显示的相匹配)。但是,在选择 item2
之后,item3
显示第一个选项(按预期)。在那之后,变更集确实包括 item1
和 item2
更改,但是 item3
selected 选项不存在。
问题:
- 如何让相关的 select 标签(
item2
和item3
)在更改第一个 select(item1
)? - 如何从相关 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
属性。接下来,根据需要更改 item2
和 item3
属性(即项目值和选定值)。最后,item2
和 item3
属性被强制转换和验证。
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
).
如果有更好的方法,我愿意接受建议。