Telerik blogs
BlazorT4_1200x303

You can enhance your wizard just by replacing the default Next/Previous buttons with your own buttons and code.

In an earlier post I pointed out how the Wizard component from Progress Telerik UI for Blazor makes it extremely easy to add a wizard to your Blazor application (an excellent tool for helping users through a difficult task). If all you need is to walk the user from the first step to the last step, really, the Wizard component doesn’t require any customization (especially if you leverage the Telerik UI for Blazor Form component to build out each step’s UI).

If you do want to customize your wizard, you’re probably going to look first at giving the user more control over the navigation process—rather than forcing the user to keep clicking their way through all of the steps, you might want to give the user the ability to skip ahead to a specific step or return quickly to an earlier one. This might include returning to the start or end steps, for example.

Giving Up Control

The easiest way to let the user pick the “next step” is to let the user pick the step they want from the list of steps across the top of the wizard. By default, users already have the ability to select the “next step” from the step list but only if they pick the step before and the step after the current step (i.e., the steps that the Next and Previous buttons would take the user to, anyway).

You can let the user select any step from the list by adding a WizardSettings element inside your TelerikWizard element and, inside that element, adding a WizardStepperSettings tag. On that tag, you can enable the user to select the step they want by setting the WizardStepperSettings’s Linear attribute to false:

<WizardSettings>
        <WizardStepperSettings Linear="false"/>        
</WizardSettings>

When the user selects a step from the list at the top, the OnChange event for the step the user is leaving still fires, just as if the user clicked the step’s Next or Previous button.

The problem with enabling this feature is that you need to make sure that, before the user clicks the Done button on the last step, that all entries are complete, correct and compatible. There is a danger in allowing the user to skip steps because your user may arrive at the last step without having entered the values expected on some earlier step.

The easiest solution to that problem is, before the user starts the wizard, to set default values for every value the user is expected to enter in every step. If earlier steps affect entries in later steps, then you may find it necessary in the code in any step to override the default values for a later step as users make entries in those earlier steps.

Even then, unless all your steps are independent of each or (failing that) no later step is affected by entries in an earlier step, you should validate all the user’s entries when the user clicks the Done button.

Taking Control Back

Another option is to supply your own custom navigation buttons to maintain some control over the user’s navigation while providing the user with some additional flexibility. If you want to fully support your users, for example, you should be providing different support for the Next button than you do for the Previous button.

To start adding your own buttons, first add a WizardButtons element, nested inside your TelerikWizard element. You don’t even have to put anything inside the WizardButtons element if you don’t want to—that will eliminate the default Next/Previous/Done buttons at the bottom of the wizard. This can make sense if you want to control moving to the “next step” from components inside each step’s Content element.

Regardless of how you intend to support having your user navigate through your wizard, you’ll need to use the TelerikWizard’s @bind-value attribute to bind some integer variable that you’ll use to control the wizard’s “current step.” This example binds a field cleverly called currentStep:

<TelerikWizard @bind-Value="currentStep">

That requires you to declare a corresponding field in your code (currentStep could also have been declared as a property):

private int currentStep = 0;

That’s all the infrastructure you need to manage the user’s navigation through the wizard with your own buttons—after this, it’s just a matter of incrementing and decrementing currentStep to move the user to any step.

Taking Control Back: Adding the Buttons

As an example of how you might customize the wizard’s buttons, you might want to give the user not only Next, Previous and Done buttons but also “Go Back to Start” and “Skip to End” buttons. That design would give the user a first step that looks like this:

A screenshot of a wizard. In the list of steps at the top of the wizard, the first step is highlighted. In the bottom right corner are three buttons. On the right is a VCR-style fast rewind button, on the right is a VCR-style fast forward button. In between is a Next button.

Second and subsequent steps like this would include a Back button:

A repeat of the previous screenshot but, in the list of steps at the top of the wizard, the second step in the wizard is highlighted. There is now a Previous button to the left of the Next button in between the two VCR buttons.

And on the last step, the Next button would magically morph into a Done button:

A repeat of the last screenshot but, in the list of steps at the top, the final step is highlighted. Next button has been replaced by a Done button

To implement this design, begin by deciding, inside the WizardSteps element, what components you want to display in each step. You can control which buttons display by wrapping components in if statements that check which step is the “current step.” You can use the pseudo-variable named context that the TelerikWizard provides to determine what the current step is. You’ll also need to bind each button to a method that will move the user to the appropriate step in the wizard.

Putting that all together, a WizardButtons section that defined Restart, Previous, Next, Done and Skip-to-End buttons would look like this:

<WizardButtons>
       @{
            <TelerikButton Icon="caret-alt-to-left" ThemeColor="secondary"
                                        OnClick="Restart"></TelerikButton>
        }
        &nbsp;&nbsp;
        @{
            if (context > 0)
            {
                <TelerikButton ThemeColor="secondary"
                                            OnClick="PreviousButton">Back</TelerikButton>
            }
            if (context < 4)
            {
                <TelerikButton ThemeColor="primary"
                                            OnClick="NextButton">Next</TelerikButton>
            }
            if (context == 4)
            {
                <TelerikButton ThemeColor="primary" 
                                            OnClick="@DoneButton">Done</TelerikButton>
            }
        }
        &nbsp;&nbsp;
        @{
            <TelerikButton Icon="caret-alt-to-right" ThemeColor="secondary"
                       OnClick="SkipToEnd"></TelerikButton>
        }       
    </WizardButtons>

Taking Control Back: Getting to the Right Step

The methods called from these buttons don’t have to be complicated: the Next and Previous buttons just need to increment or decrement the current step position; the Restart button just sets the currentStep to 0 (to go the first step); and the Skip-to-End button sets the currentStep to the number of the last step in the wizard.

That does mean that, within the methods for the Next and Previous buttons, you need to determine what the “current step” is. There are two ways to do that.

You could pass the context variable available in your Razor code to your methods. In that case, you’d need to rewrite your OnClick attributes to pass the context pseudo-variable, like this:

<TelerikButton OnClick="@( () => NextButton(context) )" …

Your NextButton and PreviousButtons will need to accept the context step number as a parameter and do the right thing with it:

private void NextButton(int onStep)
{
    currentStep = ++onStep;
}

Alternatively, you can use the TelerikWizard’s @ref attribute to bind the component to a field or property in your code. This code binds the wizard to a field cleverly called wizard:

<TelerikWizard @ref="wizard" …

The corresponding field needs to be declared as a TelerikWizard:

private TelerikWizard wizard;

In your Next and Previous button methods, you can now retrieve the current step position from the wizard field’s Value property:

private void PreviousButton()
{
   currentStep = --wizard.Value;
}

When Users Change Their Minds

However, if you consider how users actually use the Previous button, there is one enhancement you might want to add to your “next button” code.

The Previous button is there because users get smarter about the process as they work through it. As a result, users can get to your wizard’s Step 5 and—now that they’re further into the process and correspondingly smarter—realize that they made an unfortunate choice back in Step 2. When that happens, the user will want to go back and change their entries in the earlier step rather than either finish the current step or go on to the next one.

But this is where you might want to enhance the code behind your Next button: The user may have gotten smarter because of an error message on the current step. When there’s a problem on the page, you don’t want the user to go to the next step. However, your user may realize that the best way to fix the problem is to return to an earlier step and make a change there. While you won’t let the user go to the next step when there’s an error, you should be willing to let the user go back to a previous step.

To support that, you should enhance your Next button code to check for errors on the page before letting the user go forward (ditto for the Skip-to-End button). Assuming that you’re using a form to build out your step’s UI, your NextButton code just has to check to see which step the user is on, check the IsValid property for the form for that step, and—if there’s a problem—return without advancing the current step.

As a result, typical NextButton code could look something like this as you check combinations of the current step and IsValid properties on the steps’ forms:

private void NextButton(int onStep)
{
  if (onStep == 0 && !OverviewForm.IsValid() ||
       onStep == 1 && !PickDatesForm.IsValid() || 
      …more steps… )
  {
      return;
  }  
   currentStep = ++onStep;
}

You don’t have to do any of this, of course. But if you do want to give the user more navigation options (or do anything you want at the bottom of the wizard—provide a Cancel button, for example), you can do that. Plus, as I’ll discuss in my next post, you can also dynamically add or remove steps to the Blazor wizard component (and there’s at least one place where you’ll want to).


Peter Vogel
About the Author

Peter Vogel

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter also writes courses and teaches for Learning Tree International.

Related Posts

Comments

Comments are disabled in preview mode.