Blazor component that helps you create wizard components with sequential steps, forward/back navigation, conditional completion of steps, step- and wizard-level events, and more
$ dotnet add package VDT.Core.Blazor.WizardBlazor component that helps you create wizard components with sequential steps, forward/back navigation, conditional completion of steps, step- and wizard-level events, and more
<div>
<button @onclick="async () => await Wizard.Start()" class="btn btn-primary">Start wizard</button>
<button @onclick="() => Wizard.Stop()" class="btn btn-secondary">Stop wizard</button>
</div>
<Wizard @ref="Wizard"
OnStart="Start"
OnStop="Stop"
OnFinish="Finish"
ContainerClass="wizard"
TitleContainerClass="wizard-title"
StepTitleContainerClass="wizard-steps"
StepTitleClass="wizard-step"
ActiveStepTitleClass="active"
AllowCancel="true"
AllowPrevious="true"
ButtonContainerClass="wizard-buttons"
ButtonClass="wizard-button"
ButtonCancelClass="wizard-button-secondary"
ButtonCancelText="Stop"
ButtonPreviousClass="wizard-button-secondary"
ButtonPreviousText="<< Prev"
ButtonFinishClass="wizard-button-primary"
ButtonFinishText="Complete"
ButtonNextClass="wizard-button-primary"
ButtonNextText="Next >>"
ContentContainerClass="wizard-body">
<TitleContent>
<h3>Wizard title</h3>
</TitleContent>
<Steps>
<WizardStep OnInitialize="args => InitializeStep(args, 1)" OnTryComplete="args => TryCompleteStep(args, 1)" Title="The first step">
Test step 1
</WizardStep>
<WizardStep OnInitialize="args => InitializeStep(args, 2)" OnTryComplete="args => TryCompleteStep(args, 2)" Title="Another">
<div class="form-check">
<input id="goNext" type="checkbox" @bind="GoNext" class="form-check-input" />
<label for="goNext" class="form-check-label">Go next?</label>
</div>
<div>
Test step 2
</div>
</WizardStep>
<WizardStep OnInitialize="args => InitializeStep(args, 3)" OnTryComplete="args => TryCompleteStep(args, 3)" Title="Summary">
Test step 3
</WizardStep>
</Steps>
</Wizard>
<pre>
@StepData
</pre>
@code {
public Wizard Wizard { get; set; }
public bool GoNext { get; set; } = true;
public string StepData = string.Empty;
public void Start(WizardStartedEventArgs args) {
StepData += $"{nameof(Start)} wizard{Environment.NewLine}";
}
public void Stop(WizardStoppedEventArgs args) {
StepData += $"{nameof(Stop)} wizard{Environment.NewLine}";
}
public void Finish(WizardFinishedEventArgs args) {
StepData += $"{nameof(Finish)} wizard{Environment.NewLine}";
}
public void InitializeStep(WizardStepInitializedEventArgs args, int step) {
StepData += $"{nameof(InitializeStep)} step {step}{Environment.NewLine}";
GoNext = true;
}
public void TryCompleteStep(WizardStepAttemptedCompleteEventArgs args, int step) {
StepData += $"{nameof(TryCompleteStep)} step {step}{Environment.NewLine}";
args.IsCancelled = !GoNext;
}
}
ContainerClass gets applied to a div surrounding the entire wizard when using the default layoutTitleContainerClass gets applied to a div surrounding the title content when using the default layoutStepTitleContainerClass gets applied to a div surrounding the step titles when using the default layoutStepTitleClass gets applied to the step title divsActiveStepTitleClass gets applied to the active step title divButtonContainerClass gets applied to a div surrounding the navigation buttons when using the default layoutButtonClass gets applied to all navigation buttonsButtonCancelClass gets applied to the cancel buttonButtonPreviousClass gets applied to the previous buttonButtonNextClass gets applied to the next buttonButtonFinishClass gets applied to the finish buttonContentContainerClass gets applied to a div surrounding the content of the currently active step when using the default layoutYou can subscribe to several events during the wizard's life cycle; most are informational only but some allow you to manipulate the wizard's behaviour.
Wizard.OnStart event fires when the wizard is started.Wizard.OnStop event fires when the wizard is stopped.Wizard.OnFinish event fires when the wizard is finished because all steps of the wizard have been completed.WizardStep.OnInitialize event fires when a step is rendered.WizardStep.OnTryComplete event fires when a step is completed by clicking the Next button. The provided WizardStepAttemptedCompleteEventArgs lets you
see if the step has been previously completed and lets you cancel completion of a step.If the default wizard layout does not suffice, it's easy to customize the layout by using the Layout renderfragment and the various renderfragments found on
the context provided by it. If you provide a layout template the default container elements will not be used and their CSS classes will not be applied, but
any properties for specific renderfragments for buttons or other common elements, such as CSS, titles and the various allow options will still be applied.
context.DefaultLayout renders the wizard title contentcontext.Title renders the wizard title contentcontext.StepTitles renders the wizard step titlescontext.Buttons renders the wizard cancel, previous, next and finish buttons if they are available and enabledcontext.ButtonCancel renders the wizard cancel button if enabledcontext.ButtonPrevious renders the wizard previous button if enabled and there is a previous stepcontext.ButtonNext renders the wizard next button if there is a next stepcontext.ButtonFinish renders the wizard finish button if this is the final stepcontext.ActiveStepContent renders the wizard active step contentFor further customization, you can create a layout without using any renderfragments, instead using only properties and methods of the wizard that can be
accessed via context.Wizard.
This does not list Blazor parameters such as button texts or any of the CSS classes.
IsActive indicates whether or not the wizard is currently activeActiveStepIndex is the index of the currently active step if the wizard is active, otherwise nullActiveStep is the currently active step if the wizard is active, otherwise nullIsFirstStepActive indicates if the first step in the wizard is the currently active oneIsLastStepActive indicates if the last step in the wizard is the currently active oneAllSteps returns all available wizard steps in order of displayStart() opens the wizard at the first step if it's not currently activeStop() closes and reset the wizard if it's currently activeGoToPreviousStep() goes to the previous step in this wizard if it is active and it's not on the first stepTryCompleteStep() attempts to complete the current step, then either move to the next step or complete the wizardGoToStep(...) navigates to a specific step in the wizard if it is active, after optionally attempting to complete the currently active step
GoToStep(WizardStep step, bool tryCompleteStep)GoToStep(int stepIndex, bool tryCompleteStep)GoToStep(StepIndexProvider stepIndexProvider, bool tryCompleteStep)This does not list Blazor parameters such as Title.
IsActive indicates whether or not the wizard step is currently activeIsCompleted indicates whether or not this step has been previously completed; resets to false when the wizard is closedThis example wizard does not use any of the renderfragments, instead showing how to create a completely new layout with the same functionality and added navigation and indication for completed steps.
<Wizard @ref="Wizard">
<TitleContent>
<h2>Wizard title</h2>
</TitleContent>
<Layout>
<div class="card">
<div class="card-header">
@context.Title
</div>
<div>
<div class="d-flex align-items-stretch">
<div class="flex-grow-0 border-end bg-light px-3 py-2">
@foreach (var step in context.Wizard.AllSteps) {
<div class="me-3">
@if (step.IsActive) {
<span class="fw-bold">@step.Title</span>
}
else if (step.IsCompleted) {
<button class="btn btn-link p-0 align-baseline" @onclick="() => context.Wizard.GoToStep(step, false)">@step.Title</button>
}
else {
<span>@step.Title</span>
}
@if (step.IsCompleted) {
<span class="text-success fw-bold ps-1">✓</span>
}
</div>
}
</div>
<div class="flex-grow-1 px-3 py-2">
@context.ActiveStepContent
</div>
</div>
</div>
<div class="card-footer d-flex">
<div class="flex-grow-1">
<button class="btn btn-secondary" @onclick="context.Wizard.Stop">Stop</button>
</div>
<div class="flex-grow-0 btn-group">
@if (!context.Wizard.IsFirstStepActive) {
<button class="btn btn-secondary" @onclick="context.Wizard.GoToPreviousStep"><< Prev</button>
}
@if (context.Wizard.IsLastStepActive){
<button class="btn btn-primary" @onclick="context.Wizard.TryCompleteStep">Complete</button>
}
else {
<button class="btn btn-primary" @onclick="context.Wizard.TryCompleteStep">Next >></button>
}
</div>
</div>
</div>
</Layout>
<Steps>
<WizardStep Title="Introduction">
<p>
This is an example wizard with a custom layout. Please click Next to continue.
</p>
</WizardStep>
<WizardStep Title="Your step here">
<p>
This is the second step in this wizard. Please click Next to continue.
</p>
</WizardStep>
<WizardStep Title="Summary">
<p>
Please click Complete to finish the wizard.
</p>
</WizardStep>
</Steps>
</Wizard>
@code {
private Wizard? Wizard { get; set; }
}