phoenixframework / phoenix_live_view

Rich, real-time user experiences with server-rendered HTML
https://hex.pm/packages/phoenix_live_view
MIT License
6.24k stars 934 forks source link

Nested form fields do not display errors #3493

Closed honungsburk closed 1 week ago

honungsburk commented 2 weeks ago

Environment

Actual Behavior

When using nested forms, validation errors are not displayed correctly. Errors are only shown for top-level fields not nested fields.

Reproduction Steps

The issue can be reproduced in this example repository: phoenix_single_file_nested_form_validation

Expected Behavior

Nested forms should properly display validation errors.

honungsburk commented 2 weeks ago

If you agree that this is a bug I might be able to set off some time to fix it.

SteffenDE commented 2 weeks ago

I think it's a bug. I actually came across this recently as well, but didn't have the time to look into it. You can workaround this by using the preferred syntax (for change tracking, it is better to use @form directly) and not use :let={f} when you already have a form struct:

    <.form for={@form} as={:form} phx-submit="validate" class="flex flex-col gap-4 max-w-sm mx-auto">
      <.input field={@form[:field_one]} label="Errors are shown" />
      <.inputs_for :let={nested_form} field={@form[:nested_form]}>
        <.input field={nested_form[:field_two]} label="Errors are not shown" />
      </.inputs_for>
      <.button>Validate</.button>
    </.form>

So something gets broken when we create the form we pass to the slot.

honungsburk commented 2 weeks ago

@SteffenDE Do you have a trick for supporting multiple levels of nesting? Your trick works for one level of nesting but not deeper.

Non-working example:

    <.form for={@form} as={:form} phx-submit="validate" class="flex flex-col gap-4 max-w-sm mx-auto">
      <.input field={@form[:field_one]} label="Errors are shown" />
      <.inputs_for :let={nested_form} field={@form[:nested_form]}>
        <.input field={nested_form[:field_two]} label="Errors are not shown" />
        <.inputs_for :let={double_nested_form} field={nested_form[:double_nested_form]}>
          <.input field={double_nested_form[:field_three]} label="Errors are not shown" />
        </.inputs_for>
      </.inputs_for>
      <.button>Validate</.button>
    </.form>
SteffenDE commented 2 weeks ago

I do not, but it’s probably the same underlying reason. I’ll try to investigate!

SteffenDE commented 2 weeks ago

@honungsburk I just tried to reproduce the double nested case, but it works fine for me? Did you maybe forget to cast_embed the double_nested_form?

https://gist.github.com/SteffenDE/f9a10f527ae1b6f87caff61f5ddfb105

honungsburk commented 2 weeks ago

@honungsburk I just tried to reproduce the double nested case, but it works fine for me? Did you maybe forget to cast_embed the double_nested_form?

https://gist.github.com/SteffenDE/f9a10f527ae1b6f87caff61f5ddfb105

Yep, I added the cast_embed and now the double nesting works.