StatifierBlocks.Editor.ConfigForm (StatifierBlocks v0.1.0)

Copy Markdown View Source

The selected block's config form (ADR-0005 decisions 9 and 13).

The form is a projection of current config, never a stateful mirror of it: StatifierBlocks.ViewModel re-derives config_schema/1 against the block's current config on every build, so a branch that gains an arm gains a field on the very next render with nothing here to invalidate.

Two things this component does not do, both deliberate:

form.unrouted renders at the head. That bucket exists because Core.Branch.config_schema/1 keys one field per arm by the arm's own slot name while validate_config/1 also emits findings keyed "arms" - a key matching no field, because adding or removing an arm is a document edit, not a form value. Rendering it here is what stops such a finding from silently having nowhere to go.

Summary

Functions

One block's form: unrouted findings, then a control per schema field.

Decodes a phx-change payload into a config map, one field at a time through StatifierBlocks.Editor.Field.decode/2.

Functions

config_form(assigns)

One block's form: unrouted findings, then a control per schema field.

Attributes

  • node (StatifierBlocks.ViewModel.Node) (required)
  • target (:any) (required)
  • class (:string) - Defaults to nil.
  • expression_component (:any) - Defaults to nil.

decode(fields, params, base \\ %{})

Decodes a phx-change payload into a config map, one field at a time through StatifierBlocks.Editor.Field.decode/2.

Three properties, each of which is a bug if it is missing:

  • It starts from base, the config the block already carries. An :update_config command replaces a block's whole config, so a decode that built a fresh map from the schema alone would delete every key the schema does not name. ADR-0002 decision 7 makes config_schema/1 a rendering hint rather than the authority, and ADR-0001 decision 9's principle - leave alone what you do not understand - applies to config keys as much as to block types.
  • It is keyed off the schema, not off the params. A param naming something the schema does not is ignored, so a crafted payload cannot inject config keys.
  • A field whose control did not post keeps the value it had. A partially rendered form does not blank out the fields it did not show.

Where a decoded value is written

A field's key names its control; where the value goes is the field's value_path (ADR-0002 decision 7, amended 2026-08-27), which is [key] unless the block type said otherwise. Core.Branch is the one core type that says otherwise: its per-arm condition fields keep their slot-name keys and declare ["arms", i, "cond"], so a branch's conditions are editable here without this component ever inferring anything from the shape of a key. Writing through the path is also what stops a top-level config["arm_approved"] from accumulating beside the arm the author actually edited.