# `MishkaGervaz.Form.Web.Events`
[🔗](https://github.com/mishka-group/mishka_gervaz/blob/v0.0.2/lib/mishka_gervaz/form/web/events.ex#L1)

Handles all form events for MishkaGervaz.

This module centralizes event handling for:
- Validation (phx-change)
- Submission (phx-submit)
- Wizard step navigation
- Upload events
- Relation field search/select
- Cancel
- Reset — starts the form over as an empty create form, see `MishkaGervaz.Form.Web.Live.reset/2`
- Nested/array field management

## Sub-builders

Events functionality is split into specialized sub-builders:

- `SanitizationHandler` - Input sanitization
- `ValidationHandler` - Form validation
- `SubmitHandler` - Form submission
- `StepHandler` - Wizard step navigation
- `UploadHandler` - File upload events
- `RelationHandler` - Relation field search/select
- `HookRunner` - Hook execution

## Customization

You can override individual sub-builders via DSL:

    mishka_gervaz do
      form do
        events do
          sanitization MyApp.CustomSanitizationHandler
          validation MyApp.CustomValidationHandler
          submit MyApp.CustomSubmitHandler
          step MyApp.CustomStepHandler
          upload MyApp.CustomUploadHandler
          hooks MyApp.CustomHookRunner
        end
      end
    end

Or override the entire Events module:

    mishka_gervaz do
      form do
        events MyApp.CustomFormEvents
      end
    end

See `MishkaGervaz.Form.Web.Events.Helpers` (shared helpers exposed to
sub-handlers and user overrides), `MishkaGervaz.Form.Web.State`,
`MishkaGervaz.Form.Web.DataLoader`,
`MishkaGervaz.Form.Web.Live`, and the sub-handlers
`SanitizationHandler`, `ValidationHandler`, `SubmitHandler`,
`StepHandler`, `UploadHandler`, `RelationHandler`, `HookRunner`.

# `socket`

```elixir
@type socket() :: Phoenix.LiveView.Socket.t()
```

# `state`

```elixir
@type state() :: MishkaGervaz.Form.Web.State.t()
```

# `handle`

```elixir
@callback handle(event :: String.t(), params :: map(), socket :: socket()) ::
  {:noreply, socket()}
```

# `clear_list_field_values`

```elixir
@spec clear_list_field_values(MishkaGervaz.Form.Web.State.t()) ::
  MishkaGervaz.Form.Web.State.t()
```

Run on every `validate`: drops the rows `add_list_item` and `remove_list_item` hold for each
`:string_list` field, so the field draws the items the form posted.

Every other value in `state.field_values` is kept, a relation's selection among them.

# `handle`

```elixir
@spec handle(String.t(), map(), socket()) :: {:noreply, socket()}
```

Dispatches one `phx-` event to the default handler.

The entry point `MishkaGervaz.Form.Web.Live` calls for every form event. A resource that
wires `events do module MyApp.Form.Events end` replaces this; one that overrides a single
sub-handler leaves it alone and the dispatcher routes through the override.

# `put_select_picks`

```elixir
@spec put_select_picks(MishkaGervaz.Form.Web.State.t(), map()) ::
  {MishkaGervaz.Form.Web.State.t(), [atom()]}
```

Run on every `validate` and `save`: writes into `state.field_values` the pick each relation field
drawn as a plain select (`MishkaGervaz.Form.Types.Field.Relation.select_mode?/1`) posted in
`params["form"]`.

An empty pick takes the field's value out of `state.field_values`. A field the select did not
post, or one the user may not change (`MishkaGervaz.Form.Web.Events.SubmitHandler.field_protected?/2`),
keeps its value.

Returns the state and the names of the fields whose value the picks changed. `validate` empties
and reloads the fields that depend on them, as `relation_select` does.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
