PhoenixKitEntities.Components.FieldInput (PhoenixKitEntities v0.4.6)

Copy Markdown View Source

Control-only inline renderer for ONE entity field — the embeddable primitive under FormBuilder.build_field/3's full form blocks. Hosts that lay records out their own way (compact rows, table cells, chips) render <.field_input> per field and keep full ownership of layout, labels, and persistence, while every field type — including ones added to entities later — renders correctly without host changes.

The save contract

The host wraps its inputs in a <form phx-change="..." phx-submit="..."> it owns (include hidden inputs for row identity — a record uuid — and read _target to know which field changed). phx-submit is load-bearing even when the change event does all the saving: a form with phx-change but no phx-submit is treated as external by LiveView, so Enter in a typed input native-submits and navigates away, killing the socket. Point it anywhere harmless — a clause that no-ops on payloads without _target works.

  • Typed inputs (text, textarea, email, url, rich_text, number, date) carry phx-debounce="blur", so the form's change event fires on blur/enter — not per keystroke.
  • Discrete inputs (boolean toggle, select, radio, checkbox group) fire immediately. Booleans pair the checkbox with a hidden "false" input and checkbox groups a hidden "", so the change payload always carries the key even when everything is unticked. Checkbox groups submit under name[] (not the bare name), so the host reads a list at that key — cast_field/2 normalizes it, dropping the hidden "" entry.
  • Media references (image, video) are not form inputs at all: they render the current file (thumbnail for images) plus Choose/Clear buttons that push the host's on_pick/on_clear events with phx-value-field={field key} and any pick_params. The host opens its media picker (e.g. core's MediaSelectorModal) and writes the chosen storage file uuid through its own save path.

Cast the change payload with PhoenixKitEntities.FormBuilder.cast_field/2 before persisting — it applies the same per-type coercion and validation the full form pipeline uses.

Nested forms are invalid HTML: this component renders bare controls precisely so it can live inside whatever form (or none) the host has; the host is responsible for the form context.

Example

<form
  id={"row-#{value.uuid}"}
  phx-change="extras_changed"
  phx-submit="extras_changed"
>
  <input type="hidden" name="uuid" value={value.uuid} />
  <.field_input
    :for={field <- @entity.fields_definition}
    field={field}
    name={"extras[#{field["key"]}]"}
    value={value.data[field["key"]]}
    size="xs"
    on_pick="pick_extra_media"
    on_clear="clear_extra_media"
    pick_params={%{"uuid" => value.uuid}}
  />
</form>

Summary

Functions

Renders the control for one field definition. See the moduledoc for the save contract per field-type family.

Functions

field_input(assigns)

Renders the control for one field definition. See the moduledoc for the save contract per field-type family.

Attributes

  • field (:map) (required) - one fields_definition entry (string keys).

  • name (:string) (required) - form input name, e.g. extras[price]. Checkbox groups append [] (real options and the hidden "" fallback both submit under name[]), so the host reads a list at that key.

  • value (:any) - Defaults to nil.

  • id (:string) - derived from name when absent. Defaults to nil.

  • size (:string) - Defaults to "sm". Must be one of "xs", "sm", or "md".

  • disabled (:boolean) - Defaults to false.

  • class (:string) - extra classes merged onto the styled control — for daisyUI modifiers or layout the host owns, e.g. join-item when the field sits inside a joined group. Defaults to nil.

  • form (:string) - id of the owning <form> when the control renders OUTSIDE it (the HTML form attribute) — e.g. table layouts, where a <form> inside <tr> gets foster-parented out by the HTML parser. Applied to every native control including the hidden fallbacks.

    Defaults to nil.

  • on_pick (:string) - event pushed by the image/video Choose button (required for those types). Defaults to nil.

  • on_clear (:string) - event pushed by the image/video Clear button (hidden when absent). Defaults to nil.

  • pick_params (:map) - extra phx-value-* params on the pick/clear buttons (row identity). "field" is reserved — the buttons always send the field key under it, so a pick_params entry named field is dropped.

    Defaults to %{}.