LiveComponent for MishkaGervaz admin forms.
This is a thin orchestrator that delegates to specialized modules:
State- State managementDataLoader- Record loading and relation optionsEvents- Event handlingRenderer- Template rendering
Usage
Create mode (new record):
<.live_component
module={MishkaGervaz.Form.Web.Live}
id="post-form"
resource={MyApp.Post}
current_user={@current_user}
/>Edit mode (existing record):
<.live_component
module={MishkaGervaz.Form.Web.Live}
id="post-form"
resource={MyApp.Post}
current_user={@current_user}
record_id={@post_id}
/>Required Assigns
id- Unique component IDresource- Ash resource module withMishkaGervaz.Resourceextensioncurrent_user- Current user for authorization
Optional Assigns
record_id- ID of record to edit (nil for create mode)defaults- Map of default field values for create mode (e.g.,%{workspace_id: @workspace_id}). A picker's default is saved only while the picker still holds it: once it is cleared, or emptied because a field it depends on changed, the save leaves it out. An update that leaves the key out, such as thesend_update/2a table's Edit sends with only arecord_id, keeps the defaults the form has. Passdefaults: nilto drop them.reset-truestarts the form over on itsrecord_id, even when that is the record already open, ornilwhile the form is already on create. See "Opening a form again".
Opening a form again
A form that stays mounted while it is hidden — in a modal that is shown and hidden, say — keeps what was typed, its errors and its pending uploads through a close that sends it nothing, such as a modal's close icon. Whatever opens it again starts it over:
send_update(MishkaGervaz.Form.Web.Live, id: "post-form", record_id: nil, reset: true)A create returns to the empty create form, with the form's defaults; an edit reads its record
again. The uploads are cancelled. A create is drawn once without its <form> before the empty one
is built, so every control is drawn anew, a phx-update="ignore" one included, and reads the new
value. A table's Edit sends reset: true with the row's record_id. A button that opens the form
without asking the server uses reset/2.
After a save
A create save always returns the form to an empty create form. An update save depends on how the form was mounted:
- mounted with a
record_idassign (evennil) — the form stays on the saved record, reloaded for editing. Pass a differentrecord_id, ornil, to move it. - mounted without one, and opened for editing with
send_update/2— the form returns to an empty create form.
Parent LiveView Integration
The component sends messages to the parent for certain actions:
def handle_info({:form_saved, :create, result}, socket), do: ...
def handle_info({:form_saved, :update, result}, socket), do: ...
def handle_info({:form_cancelled, resource}, socket), do: ...
def handle_info({:form_event, event, params}, socket), do: ...
def handle_info({:add_nested_field, field_name}, socket), do: ...
def handle_info({:remove_nested_field, field_name, index}, socket), do: ...See MishkaGervaz.Form.Web.State (state shape + override surface),
MishkaGervaz.Form.Web.DataLoader (record + relation loading),
MishkaGervaz.Form.Web.Events (event handling),
MishkaGervaz.Form.Web.Renderer (template dispatch),
MishkaGervaz.Form.Web.UploadHelpers, and
MishkaGervaz.Form.Behaviours.Template.
Summary
Functions
The JS command that starts the form with this component id over as an empty create form, as
reset: true with a nil record_id does. For a button that shows a hidden form on the client
Functions
@spec reset(Phoenix.LiveView.JS.t(), String.t()) :: Phoenix.LiveView.JS.t()
The JS command that starts the form with this component id over as an empty create form, as
reset: true with a nil record_id does. For a button that shows a hidden form on the client:
<button phx-click={MishkaGervaz.Form.Web.Live.reset("post-form") |> show_modal("post-modal")}>It pushes the form's reset event to the element with the id "<id>-form-wrapper".