In this article we are going to use Razor components to build a Wizard for Blazor. The focus of my articles has been on client side Blazor and MVVM but this article is specifically about Razor components and the Wizard we make should be usable in any Blazor application.

The source code for this article is built against .Net Core 3 Preview 4. Preview 5 was released last week but there were no major changes and it should be easy to update to Preview 5 if needed. All articles and source code will probably be updated again when .Net Core 3 Preview 6 is released. The source code for the start point of this article is located in my BlazorMVVM repository on GitHub.

The starting point of this article will be the ArticleSeven branch or the 4.7 release. The final code from this article will be committed as the ArticleEight branch and 4.8 release.

If you would like to read the previous article where we built the Model and ViewModel then build the Wizard manually in the View it can be read at this link:

Today we are going to replace most of the contents of our View with a Wizard built from reusable Razor components. There will be no changes to the Model and ViewModel besides renaming one field in the ViewModel. We will be refactoring the View to make our Wizard built entirely with Razor component tags.

Why use components?

The first question to ask is why are we doing this? To get an idea of what we are about to do let’s take a look at the markup needed to use the Telerik datagrid:

These six lines of markup allow a developer to take advantage off all of the work that Telerik has done on their datagrid without needing any knowledge of how the grid works under the covers. It also makes it very easy to see what the datasource is as well as that the grid will display two columns and what those two columns are. So the benefits of using components are twofold:

We can encapsulate code into a reusable component that can easily be accessed through markup. Our markup becomes easier to read through meaningful nested tags and bindings.

If we look back at the Wizard we built in the last article it was about 143 lines of code including the progress bar. Many of those lines were the same exact lines of markup repeated 8 times; once for each step of the Wizard. If we can properly encapsulate the Wizard into nested components we will have fewer lines of code and our View will be much more readable.

Starting the Wizard

First we need to decide on how the pieces of the Wizard will fit together. At our starting point we have a progress bar that sits above our Wizard, then our Wizard itself is a switch() statement which encapsulates the 8 cards that make up the Wizard. Each card contains a control which gets input from the user. Our goal today is come up with a nested component scheme that will replicate all of this while minimizing repeated markup and still maintaining the same functionality. The structure of the components we want to come up with will wind up looking like this:

<Wizard>

<InputCard>

<InputControl/>

</InputCard>

<Wizard>

We already have our input controls, the RadioButtonList and the number input we used in the last article. This means we should be able to build a Wizard component and an input card component and make everything work.

In the Components folder make a new Razor view and name it Wizard.Razor. We are going to put the progress bar into this control as well as move the previous and next buttons out of the cards and into this control. The code is almost the same as it is in our existing View for both of these elements except we need to remove all references to ViewModel. We want to be able to use this component anywhere so we can’t count on there being a ViewModel available that has all of the fields we need, each needed field will be passed in as a parameter. The start of our Wizard component now looks like this:

That markup is easy enough to understand. We have a progress bar and two buttons and are binding the needed properties and events to work with the controls. That leads us to a question though. Once we create our input card how do we make it show up inside of the wizard?

ChildContent and RenderFragment

If we want some markup or another component to be nested as part of our component we are building it is easy enough to write some markup to do that.

<OurComponent>

<SomeNestedComponent />

This is plain text but it is nested content too!

</OurComponent>

What we need is a placeholder in our component for that nested content as well as a method to pass that content in to our component. Blazor gives us that ability with a special component parameter called ChildContent. Everything we nest inside of our component in the markup gets passed in to ChildContent. To make use of this parameter we have to explicitly declare it and we have to give it the type RenderFragment. If we add ChildContent to our Wizard in between the progress bar and the buttons our markup now looks like this:

ChildContent uses the @ markup just like any other parameter passed into a component. With all of the markup in place our input parameters for our Wizard look like this:

We have our 3 variables, the RenderFragment for our nested content and two EventCallback delegates for our button clicks.

Building the input card component

Now that we can nest content inside of our Wizard let’s build our input card to nest in there. We are no longer going to be using a switch statement so we are going to design our input cards that we declare them all as nested elements of the Wizard but only render if they are the active step of the Wizard. That means the entire markup of the input card will be wrapped in an @if() statement. The content of the card will be the same as the card that we repeated 8 times in our markup with a few small changes. First, we will replace the header, title and text with parameters so that each step can have the content displayed passed to it. Second, we have removed the buttons from the card because they are now part of the Wizard parent control. Finally, we will have a ChildContent placeholder in our card so we can nest our user input inside of the card using markup.

With all of that taken into consideration create a new Razor view in our Components folder and name it WizardInputCard.razor. With all of the parameters that we need to pass in the full content of the component looks like this:

WizardStep is passed in as the actual step number of the card as declared in our View. CurrentStep is passed in from the ViewModel. When the two values are equal then the card is rendered by the client. The functionality that has required the switch statement is now encapsulated into the card. Our input card also has a RenderFragment parameter so that it can display nested content bound to ChildContent.

Building the new Wizard

Go into CvdRisk.razor and delete or comment out everything after the <br/> (line 9). Now Add the markup for the Wizard and bind the input values to the values from the ViewModel. Our View now looks like this:

If we launch the application now and navigate to the calculator we will see our empty progress bar and our two disabled navigation buttons.

Now we will nest a card inside of our Wizard and then nest our user input inside of that. Inside of our Wizard add the following nested markup:

Here we have passed in four pieces of static input to the input card as well as one field from the ViewModel. This field used to be called Step but it has now been renamed to CurrentStep to add a little extra clarity to the code. As everyone knows, naming things is hard, and that’s why we can right-click rename in Visual Studio. If we launch the risk wizard again we can now see our input card as well as our radio button list.

We can select a gender and even click next step. That makes our input card disappear though as we did not declare a step two yet.

Since we already had a fully working calculator, the rest of the Wizard is just repetition of adding 7 more WizardInputCard tags and just changing the static content we pass in as well as nesting the appropriate control. When we have all 8 cards build our View now looks like this:

The code for the View is now significantly shorter and a lot more readable. We also have the option of creating and switching in different WizardInput components to use along with or instead of our card.

Wrapping Up

Today we created a Blazor Wizard using reusable Razor components. We saw how this can eliminate redundant code as well as make our markup much more readable. We also saw how easy it is to nest our own components using ChildContent and RenderFragment. If you have any questions or comments on this article you can find me @LouisHendricks on Twitter.