DynamicForm.Instance.FromSlots (DynamicForm v0.17.6)

Copy Markdown View Source

Converts <:field>, <:group>, and <:nested> slot entries from DynamicForm.form/1 into a DynamicForm.Instance struct.

This is the slot-mode counterpart to DynamicForm.Instance.Decoder: the decoder normalizes untrusted external data (JSON, string-keyed maps), while this module normalizes compiler-produced slot entries (atom-keyed maps). Both produce the same %Instance{} structs consumed by the rest of the library.

Conversion rules

  • <:field> entries convert in template order — question types (["text", "comment", "dropdown", "radiogroup", "checkbox", "boolean", "rating", "tagbox", "file"]) become Instance.Question structs; html, image, and custom become Instance.Element structs.
  • Snake_case slot attrs map to the SurveyJS-style struct fields (visible_ifvisibleIf, labeltitle, optionschoices, ...).
  • Flattened validation attrs (min_length, max_length, min, max, pattern, format) build Instance.Validator structs; the validators attr accepts explicit %Validator{} structs or atom-keyed maps for anything the flattened attrs can't express.
  • A field with group="name" is collected into a panel element declared by a <:group name="name"> entry. The panel is emitted at the position of its first member field.
  • A field with nested="name" is collected into the templateElements of a paneldynamic question declared by a <:nested name="name"> entry. nested declares the field's data scope (its value lives inside each entry of the nested form's list value); group declares visual grouping within that scope — the two combine, and a group inside a nested form declares the same nested scope on its own declaration. See the Nested Forms guide.
  • An entry with a slot body keeps the raw slot entry in the struct's :slot field so DynamicForm.Renderer can render_slot/2 it. Bodies are in-memory only — they are dropped when the instance is JSON-encoded.

Naming and scoping

Field and <:nested> names are data keys, unique per scope (the form level is one scope; each nested form's template is another) — so a top-level name and an addresses[].name coexist, mirroring the application's schema. <:group> and <:nested> declaration names are reference targets for the flat group=/nested= attrs, so declarations are globally unique.

Validation

convert!/1 raises ArgumentError with a descriptive message for invalid definitions: missing names, duplicate names within a scope, unknown types, choice questions without options, custom fields without a body, references to undeclared groups or nested forms, group/member nested-scope mismatches, nested forms with no members, and cyclic nested references.

Summary

Functions

Validates slot entries and builds a %DynamicForm.Instance{}.

Functions

convert!(assigns)

Validates slot entries and builds a %DynamicForm.Instance{}.

Expects the assigns of DynamicForm.form/1: :id plus the :field, :group, and :nested slot lists (and optional :title and :description).