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

Handles wizard step navigation events.

## How a wizard moves

The template draws every step and shows the current one; Next is the form's submit button, so
Enter in a field presses it too. `MishkaGervaz.Form.Web.Events` handles the form's submit by step:

  * on any step but the last, it validates what the form holds and calls `advance/2`, which
    moves to the next step when `can_advance?/2` allows it. A step it refuses is marked `:error`
    and shows the errors of its own fields (`step_errors/2`), never another step's, and they
    follow what is typed until the step moves on. Nothing is saved.
  * on the last step, it saves. A save that fails on a field of another step calls
    `goto_errors/2`, which moves the form to the first step holding an error, marks every step
    holding one `:error`, and sends the parent LiveView `{:put_flash, :error, message}`, the
    message naming the step to check.

Back (`prev_step`) moves to the previous step. Every step stays in the form, so nothing typed on
either is lost.

## Overridable Functions

- `can_advance?/2` - Check if user can move to next step
- `advance/2` - Move to the next step
- `go_back/2` - Move to the previous step
- `goto_step/3` - Jump to a specific step (tabs mode)
- `goto_errors/2` - Move a form whose save failed to the step holding the error

## User Override

    defmodule MyApp.Form.StepHandler do
      use MishkaGervaz.Form.Web.Events.StepHandler

      def can_advance?(state, current_step) do
        # Custom step validation
        super(state, current_step)
      end
    end

Top-level helpers `find_next_step/2`, `find_prev_step/2`, `step_exists?/2`, `step_fields/2` and
`step_errors/2` are public so user overrides can reuse them.

See `MishkaGervaz.Form.Web.Events`,
`MishkaGervaz.Form.Web.State` (for `:current_step`, `:step_states`,
`:wizard_history`), and the sibling sub-handlers.

# `step_errors`

```elixir
@spec step_errors(map(), atom()) :: %{required(atom()) =&gt; [String.t()]}
```

The errors the validated form (`state.form`) holds on the fields of step `step_name`
(`step_fields/2`), by field, each message translated. Empty when the form holds none there.

# `step_fields`

```elixir
@spec step_fields(map(), atom()) :: [atom()]
```

The names of the fields step `step_name` draws for the current reader, in its groups' order: the
fields of its groups that are `visible`, not `restricted` for the reader, and shown in the form's
mode.

---

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