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

Handles all table events for MishkaGervaz.

This module centralizes event handling for:
- Sorting
- Filtering
- Row actions (delete, edit, custom events)
- Bulk actions
- Row expansion
- Archive status changes
- Pagination

## Sub-builders

Events functionality is split into specialized sub-builders:

- `SanitizationHandler` - Input sanitization
- `RecordHandler` - Record CRUD operations
- `SelectionHandler` - Selection state management
- `BulkActionHandler` - Bulk action execution
- `HookRunner` - Hook execution
- `RelationFilterHandler` - Relation filter search/select events

## Customization

You can override individual sub-builders via DSL:

    mishka_gervaz do
      table do
        events do
          sanitization MyApp.CustomSanitizationHandler
          record MyApp.CustomRecordHandler
          selection MyApp.CustomSelectionHandler
          bulk_action MyApp.CustomBulkActionHandler
          hooks MyApp.CustomHookRunner
          relation_filter MyApp.CustomRelationFilterHandler
        end
      end
    end

Or override the entire Events module:

    mishka_gervaz do
      table do
        events MyApp.CustomEvents
      end
    end

See `MishkaGervaz.Table.Web.Events.SanitizationHandler`,
`MishkaGervaz.Table.Web.Events.RecordHandler`,
`MishkaGervaz.Table.Web.Events.SelectionHandler`,
`MishkaGervaz.Table.Web.Events.BulkActionHandler`,
`MishkaGervaz.Table.Web.Events.HookRunner`,
`MishkaGervaz.Table.Web.Events.RelationFilterHandler`,
`MishkaGervaz.Table.Web.State`,
`MishkaGervaz.Table.Web.DataLoader`,
`MishkaGervaz.Table.Web.Live`.

# `socket`

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

# `state`

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

# `handle`

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

Main event handler dispatcher.

Called from LiveComponent's handle_event callback.

# `do_delete`

```elixir
@spec do_delete(
  MishkaGervaz.Table.Web.State.t(),
  map(),
  Phoenix.LiveView.Socket.t(),
  map()
) ::
  {:noreply, Phoenix.LiveView.Socket.t()}
```

Deletes one record, runs the `:delete` action hooks and the `after_delete` hook, then drops
the row from the stream and the header count.

`params` are the `"delete"` event's params; their `"action"` names the row action a failed
delete's flash is labelled with (see `row_action_label/3`).

Public so a `RecordHandler` override can defer the destroy itself to the default behaviour
rather than re-implementing the surrounding bookkeeping.

# `handle`

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

Main event handler dispatcher.

Called from LiveComponent's handle_event callback.

# `report_row_error`

```elixir
@spec report_row_error(
  MishkaGervaz.Table.Web.State.t(),
  atom(),
  any(),
  any(),
  Phoenix.LiveView.Socket.t()
) :: Phoenix.LiveView.Socket.t()
```

Runs a failed row action's `on_row_action_error` hook, then puts the error flash. A hook answering
`{:halt, socket}` puts no flash.

# `row_action_label`

```elixir
@spec row_action_label(MishkaGervaz.Table.Web.State.t(), map(), atom()) ::
  String.t() | nil
```

The label of the row action a failed row event ran, for its error flash, or `nil` when the action
declares none.

`params` are the event's params. The action is the row action of `type` named by `"action"`, else
the one `"event"` names, else the first row action of `type`, dropdown items included.

---

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