Multi-Step Wizard
Step-by-step form with per-step validation and progress indicator.
Live Demo
Account
Profile
3
Confirm
Email:
Name:
Role:
Source
HTML + JavaScript
<div data-component="signup-wizard">
<!-- Step indicators -->
<div class="wizard-steps">
<div data-bind-class="currentStep >= 1
? (currentStep > 1 ? 'step completed' : 'step active')
: 'step'">1. Account</div>
<div data-bind-class="...">2. Profile</div>
<div data-bind-class="...">3. Confirm</div>
</div>
<!-- Step 1: the form's submit runs validation first; nextStep only
fires when every required field is valid -->
<div data-show="currentStep === 1">
<form data-validate-on="submit,blur" data-action="nextStep" novalidate>
<label>Email <small>required</small></label>
<input type="email" data-model="email" required>
<span data-error-for="email" style="display: none"></span>
<label>Password <small>required, 6+ characters</small></label>
<input type="password" data-model="password" required minlength="6">
<span data-error-for="password" style="display: none"></span>
<button type="submit">Next</button>
</form>
</div>
<!-- Step 2: nothing here is required, so Next is a plain action -->
<div data-show="currentStep === 2">
<label>Display Name <small>optional</small></label>
<input data-model="displayName" data-model-trim>
<label>Role <small>required</small></label>
<select data-model="role">...</select>
<button data-action="prevStep">Back</button>
<button data-action="nextStep">Next</button>
</div>
<!-- Step 3: Confirm -->
<div data-show="currentStep === 3">
<p>Email: <span data-bind="email"></span></p>
<p>Name: <span data-bind="displayName"></span></p>
<button data-action="submitWizard">Create Account</button>
</div>
</div>
<script>
wildflower.component('signup-wizard', {
state: {
currentStep: 1, submitted: false,
email: '', password: '',
displayName: '', role: 'developer'
},
nextStep() { this.currentStep++; },
prevStep() { this.currentStep--; },
submitWizard() { this.submitted = true; }
});
</script>
Key Points
data-show="currentStep === N"swaps step panels, only one visible at a timedata-validate-on="submit,blur"validates each field as the user tabs away and again when the step is submitted, writing the browser's own message into eachdata-error-forslot- Step 1's Next is the form's submit button and
data-action="nextStep"sits on the form, so the action only fires once every required field is valid; an empty or malformed field shows its message instead of silently doing nothing - Every field is labeled required or optional, and only the required ones carry
required,type="email"orminlength; the constraints are the labels' contract data-model-trimon the name input strips whitespace automatically- Step 3 uses
data-bindto display collected values for review before submission