DynamicForm.Components (DynamicForm v0.17.6)

Copy Markdown View Source

Resolution and dispatch for the pluggable components module.

DynamicForm renders inputs, labels, and errors through DynamicForm.CoreComponents by default. Applications can point the library at their own components module — typically the Phoenix-generated MyAppWeb.CoreComponents — either globally:

config :dynamic_form, components: MyAppWeb.CoreComponents

or per form:

<DynamicForm.form id="contact-form" components={MyAppWeb.CoreComponents}>

The per-form attribute wins over the config; without either, the built-in module renders everything.

The contract, and per-function fallback

Dispatch is per function: each component the renderer needs is looked up on the configured module with function_exported?/3, falling back to the built-in implementation when the module doesn't define it. A module only needs to define the functions it wants to own:

FunctionRendersPhoenix-generated CoreComponents?
input/1text, email, number, textarea, select, checkbox controls (receives field, type, label, and per-type extras like options/prompt/multiple)yes — works out of the box
input_radio_group/1radiogroup and rating questionsno — built-in fallback
input_checkbox_group/1multi-select checkbox groupsno — built-in fallback
label/1, error/1around custom-control slot bodiesno (private in Phoenix 1.8) — built-in fallback
section/1panelsno — built-in fallback
nested_entry/1the container around each repeating nested-form entry (receives index, name, and the entry contents as inner_block)no — built-in fallback
button/1the submit buttonyes — delegates when exported
translate_error/1error messages (routes through the app's Gettext)yes — delegates when exported

Delegation is intentionally NOT a blanket "send everything to input/1": a Phoenix-generated input/1 ends in a catch-all clause, so an unknown type like "radio-group" would render a broken <input type="radio-group"> instead of raising. The named-function contract keeps every control either correctly delegated or correctly built-in.

Summary

Functions

Whether the components module provides its own fun/1 implementation.

Renders the component fun with assigns, delegating to the components module when it exports the function and falling back to DynamicForm.CoreComponents otherwise.

Resolves the components module: the per-form value when given, otherwise the :components application config, otherwise nil (built-in only).

Translates an error tuple, delegating to the components module's translate_error/1 when exported — routing messages through the application's own Gettext — and falling back to the built-in translation with the given Gettext backend otherwise.

Functions

provides?(module, fun)

Whether the components module provides its own fun/1 implementation.

render(components, fun, assigns)

Renders the component fun with assigns, delegating to the components module when it exports the function and falling back to DynamicForm.CoreComponents otherwise.

resolve(module)

Resolves the components module: the per-form value when given, otherwise the :components application config, otherwise nil (built-in only).

Raises ArgumentError when the module cannot be loaded, so a typo fails loudly instead of silently falling back to the built-in components.

translate_error(components, error, gettext_backend \\ DynamicForm.Gettext)

Translates an error tuple, delegating to the components module's translate_error/1 when exported — routing messages through the application's own Gettext — and falling back to the built-in translation with the given Gettext backend otherwise.