Split a form into steps
v0.0.1
A Gervaz form can show its groups one step at a time as a wizard, or as tabs the reader moves between freely. This guide switches a form to each mode, defines the steps, controls how the reader moves, and gates a step with your own rule. The examples come from the wizard and tabs resources in the Gervaz test suite. No form in Mishka CMS uses steps.
Before you begin
- Have a form with fields and groups. A step names groups, not fields, so every field needs a group. See Build an admin form.
Pick a layout mode
The layout section sets the mode:
| Mode | Steps | Behavior |
|---|---|---|
:standard | Forbidden | One page. The default. |
:wizard | Required | One step at a time, in order. |
:tabs | Required | Every step is a tab. navigation :free is allowed. The Standard template draws it like a wizard, one step at a time. |
The hierarchy is step, then groups, then fields. A group may sit in at most one step.
Define the steps of a wizard
Each step lists its groups. Its ui block sets the label in the step indicator. The Standard template passes only the name, label and state of each step to the indicator, so icon, description and class are accepted but not drawn.
groups do
group :basic do
fields [:title, :content]
end
group :meta do
fields [:status, :priority]
end
group :flags do
fields [:featured]
end
end
layout do
mode :wizard
columns 2
navigation :sequential
step :details do
groups [:basic]
ui do
label "Details"
icon "hero-information-circle"
description "Enter basic info"
end
end
step :settings do
groups [:meta]
ui do
label "Settings"
icon "hero-cog"
end
end
step :review do
groups [:flags]
summary true
ui do
label "Review"
icon "hero-check-circle"
end
end
end
submit do
create label: "Finish"
endThe form handles three events: next_step, prev_step and goto_step. The submit button appears on the last step, and a submit section labels it. At most one step may set summary true. Gervaz checks that when it compiles, and the built-in template draws the step like any other.
A step's visible option is accepted, but no built-in code reads it, so it does not hide a step.
Gate a step with your own rule
A step has the options action, on_enter, before_leave and after_leave, but Gervaz does not call them. Navigation goes through four overridable functions of the step handler: can_advance?/2, advance/2, go_back/2 and goto_step/3. To stop the reader from leaving a step, override can_advance?/2. When it returns false, the step is marked as an error and the wizard stays where it is.
defmodule MyApp.Form.StepHandler do
use MishkaGervaz.Form.Web.Events.StepHandler
def can_advance?(state, :details), do: state.field_values[:title] not in [nil, ""]
def can_advance?(state, step), do: super(state, step)
endWire the module in the DSL:
form do
events do
step MyApp.Form.StepHandler
end
endThe helpers find_next_step/2, find_prev_step/2 and step_exists?/2 are public, so an override can reuse them.
Add a notice to some steps
A form notice can show on named steps only. only_steps takes step names, and Gervaz reports one that does not exist when it compiles. This notice binds to the form's errors and shows on the first two steps of the wizard above:
layout do
notice :validation_summary do
position :form_top
type :error
bind_to :validation
title fn _state -> "Please fix the errors below" end
only_steps [:details, :settings]
end
endNext steps
- Form groups and layout DSL: every option of a layout, a step and a notice.
- Override a builder, handler or loader: how a handler plugs in.
- Troubleshooting: the messages for steps and groups.