This content originally appeared on Telerik Blogs and was authored by Peter Vogel
Once you’ve added the Blazor Stepper to your component, your next step is to integrate the Stepper with your UI. You’ve got a bunch of options and here’s how to implement all of them.
In a previous blog, I showed how you can use the Stepper component from the Telerik UI for Blazor components to create a UI that breaks a “difficult task” down into a step-by-step process.
The next step is to add the steps that make up that process (your UI) and integrate those steps with the Stepper’s UI. There are two parts to that integration because the Stepper performs two tasks for you:
- The Stepper lets the user select the part of the process they want to do next so, when the user selects a step, your UI needs to update to reflect the user’s selected step.
- The Stepper also reports where the user is in the process so, when you move the user to a new step, you need to update the Stepper to reflect that.
For this discussion, I’m going to assume this Blazor Stepper markup:
<TelerikStepper @bind-value="currentStep">
<StepperSteps>
<StepperStep Label="Overview"
Icon="info-circle" ></StepperStep>
<StepperStep Label="Pick Date Range"
Icon="calendar" ></StepperStep>
<StepperStep Label="Select Occurrences"
Icon="link" ></StepperStep>
<StepperStep Label="Define Case"
Icon="folder-open" ></StepperStep>
<StepperStep Label="Save Changes"
Icon="save" ></StepperStep>
</StepperSteps>
</TelerikStepper>
That would give this UI:
To give you the control you need over the Stepper, the bind-value
attribute in the TelerikStepper
element will need to bind the control to an integer field (or property) in your code like this one:
int CurrentStep = 0;
Using bind-value
implements two-way data binding: When the user selects a step in the Stepper, the currentStep
field will be updated to show the current step’s index (i.e., if the user is on the second step, currentStep
will be set to 1); if, in your code, you update the currentStep
field, the corresponding step in the Stepper will be selected.
Showing All the Steps: Updating the Stepper
One solution for integrating your UI and the Stepper is to display all the steps in the process at once. With this design, you need to highlight each step in your UI as the user moves through the Stepper. This approach does allow the user to see the whole process in the UI (which, depending on how intimidating the process is, may or may not be helpful to the user).
Another note: With this design, to prevent Stepper from eventually scrolling off the top of the screen as the user moves through the steps, you either need some clever CSS or to have all the steps fit on a single screen with the Stepper. I’ll just assume you’ve addressed that problem in the rest of this discussion.
With this design, you must:
- Enclose each step inside a
div
orspan
element (this also facilitates formatting the steps individually) - Select an event on the elements that make up the step that signals the user has moved into that step
- On the enclosing element, bind your selected event to a method that will update the current step in the Stepper
When selecting the event to flag that the user has moved into a step, you must select how an event will bubble up to the enclosing element: onfocusin
or onclick
are good choices.
As an example, the following code binds the onfocusin
event of a div
element to a method called instep
, passing the position of the step. When the user moves to either of the textboxes, the textbox’s focusin
event will fire, the event will then bubble up to the div
element, and the method bound to div
element’s inStep
event will be called:
<div @onfocusin="() => inStep(2)">
Date Start: <input type="date" @bind-value="startDate"/>
Date End: <input type="date" @bind-value="endDate"/>
</div>
In the method that you’ve bound to the enclosing element, you just need to set the field that the Stepper component is bound to (currentStep
in my case) to update the Stepper’s UI. A typical method will look like this:
private void inStep(int newStep)
{
currentStep = newStep;
}
You don’t have to write a separate method if you don’t want to. You could, instead, just put your code inside the lambda expression for your event as in this example:
<div @onfocusin="() => currentStep = 2">
Showing All the Steps: Moving to the Step
That takes care of updating the Stepper as the user moves through the steps. However, you also need to move the user to the right step as the user selects the “next step” in the Stepper. The first thing to do is add a ref
attribute to the first element in each step and bind that to a field (or property) in your code. This example binds a textbox to a field called step1TextBox
:
<div>
Start Date: <input @ref="step1Textbox" type="date" @bind-value="startDate" />
Within your code, you need to declare that field as an ElementRef
:
ElementReference step1Textbox;
To react to the user selecting the “next step” in the Stepper, you can bind a method to the StepperStep’s OnChange
event, like this:
<StepperStep Label="Pick Date Range"
Icon="calendar"
OnChange='@StepChanged'></StepperStep>
The method that you bind to the OnChange
event must accept a parameter of type StepperStepChangeEventArgs
. That parameter has a TargetIndex
property that tells you which step the user selected. Using the TargetIndex
property, you can select the field tied to the element in the step and call the field’s FocusAsync()
to move the user’s cursor into the right step (you’ll also need to flag the bound method as async):
ElementReference step1Textbox;
private async Task StepChanged(StepperStepChangeEventArgs e)
{
switch (e.TargetIndex)
{
case 0:
await step1Textbox.FocusAsync();
break;
case 1:
//…more steps…
Revealing Steps Incrementally
The alternative to having all the steps on the page at the same time is to reveal the steps as the user needs them (i.e., the typical—and familiar—wizard UI design pattern). Having only one step on the screen at a time simplifies the UI presented to the user at any one time, but it does prevent the user from seeing the whole process.
The simplest way to implement this design is, in your UI, to move each step into the case blocks of a switch statement tied to the Stepper’s bound field. As the user moves from step to step (and, as a result, updates the Stepper’s bound field), the appropriate UI is displayed:
@switch (currentStep)
{
case 0:
<div>
Date Start: <input type="date" @bind-value="startDate" />
Date End: <input type="date" @bind-value="endDate" />
</div>
break;
case 1:
…step 2 markup
break;
}
Because the user can’t move to a step without interacting with the Stepper, you don’t have to handle updating the Stepper to reflect the “current step.”
Enclosing all of every step’s UI in your switch statement can make for some messy Razor markup. A better solution might be to create a component for each step and pass a shared data item to each component in the step.
This code, for example, assumes the existence of field called pData
in the parent component that holds all the data gathered from user in the process. That field is passed to each component that then (presumably) updates the data held
in the field:
@switch (currentStep)
{
case 0:
<Step1Component ProcessData=pData></Step1Component>
break;
case 1:
<Step2Component ProcessData=pData></Step2Component>
break;
//…more cases…
The parent component—the component with the Stepper—is just responsible for initializing the process’s data object (presumably the last component in the process is responsible for using the data gathered in the earlier steps):
MasterData pData = new MasterData { startDate = DateTime.Now.AddDays(-30),
endDate = DateTime.Now
}
Each child component can accept the process’s data object by declaring a parameter to accept the object:
[Parameter]
public MasterData pData { get; set; }
The only limitation in all of this discussion is that I’ve assumed that you’re integrating the steps in your UI as part of a static process. There’s at least one standard case (and, I bet, an infinite number of non-standard cases) where your process won’t be dynamic—where you’ll need to add or remove steps. That’s my next blog post.
This content originally appeared on Telerik Blogs and was authored by Peter Vogel
Peter Vogel | Sciencx (2022-06-15T13:45:03+00:00) Master UX for Processes With the Blazor Stepper 2: Integrate With UI. Retrieved from https://www.scien.cx/2022/06/15/master-ux-for-processes-with-the-blazor-stepper-2-integrate-with-ui/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.