Best practices when needing to take in a large number of parameters?

When I have done this for very complicated forms I make sub-structs as described.

I actually use embedded Ecto schemas and write each form section as its own component, probably each disclosure section in your API example would be one component.

The forms act as any other live view form but when they validate successfully I send(self(), {:form_section, %Struct{}}) or send(self(), {:form_section, normalised_params}) to the owning live view, which itself manages whether the whole “form” is submittable or not.

When a form “unvalidates” itself, it send(self(), {:form_section, nil}) which then “unvalidates” the owner too “for free”.

Whether I send a struct or params back depends on the complexity and who I want to own the final shape. If the sub-form section doesn’t match close enough to what I want to store, it’s probably sending params back up the chain instead.

That is to say, the form may ask for dimensions for example, with a unit option, but the main data structure may always store in mm, so the component would work with a %Dimension{value, unit} but send %{value: value_in_mm} back up to the owner. This can keep the validation/processing of unit in the one component and the owner can just trust that the data its getting is already correct.

I think this gives a good balance of coupling and separation, as well pretty easy control over showing parts of a form in a workflow or whatever.

4 Likes