Blazor Dynamic Component
With .NET 6 Preview 1, the ASP.NET Core team introduced a built-in Blazor component, DynamicComponent, that allows you to render a component specified by type. When you bring in the component, you specify the Type
and optionally a dictionary of Parameters
.
You would declare the component like this:
<DynamicComponent Type="@myType" Parameters="@myParameterDictionary" />
The DynamicComponent
has a variety of applications. I find it to be valuable when working with form data. For example, you can render data based on a selected value without having to iterate through possible types.
In this post, I’ll walk through how to use the DynamicComponent
when a user selects a list from a drop-down list.
Our use case
For a quick use case, I’m using a silly loan application. I want to gather details about where someone lives now (to determine how much they pay and whatnot). The drop-down has five possible values, and I’ve got some custom components in my Shared
directory that render based on what a user selects.
- Default state: DefaultDropdownComponent.razor
- Rent: RentComponent.razor
- Own house: OwnHouseComponent.razor
- Own condo or townhouse: OwnCondoComponent.razor
- I’m Dave’s roommate (fall-through condition): DaveRoommate.razor
Generate drop-down
To generate my drop-down list, I’ll use my component name as the option value
. Here, I can use the nameof
keyword, which returns component names as constant strings.
Here’s the markup of Index.cshtml
so far:
Write change event
We now need to decide what to do when a drop-down value is selected. To get the drop-down value, we work with the ChangeEventArgs
type to get the value of the raised event—in this case, it’s the changed drop-down selection.
Before DynamicComponent
came along, this is where you’d have logic to determine which component to render. Maybe you’d have a boolean flag, then use that in Razor markup. Instead, use Type.GetType
to get the specific component to render.
Once I’m done with that, I can bind the drop-down’s onchange
event to my OnDropdownChange
method. Whenever the drop-down value changes, the method will trigger and determine which type it needs.
Finally, I can render my DynamicComponent
. I’ll place it right under my drop-down list.
<DynamicComponent Type="selectedType" />
Now we can see the page change using my DynamicComponent
.
Optional: Pass in parameters
If your components have parameters, you can optionally pass them into your DynamicComponent
. It takes a Dictionary<string, object>
. The string
is the name of your parameter, and the object
is its value.
As a quick example, I can define ComponentMetadata
through a quick class:
Then, I can create a dictionary for my components like this (only one component has a parameter):
Then, I could have logic that filters and passes in a ComponentParameters
instance to the DynamicComponent
, depending on what type I’m passing in. There’s a lot of power here—you could pass in data from an API or a database as well or even a function, as long as it returns a Dictionary<string, object>
.
You might be asking: Why not use the catch-all approach?
<DynamicComponent Type="@myType" MyParameter="Hello" MySecondParameter="Hello again" />.
According to Blazor architect Steve Sanderson, he says:
If we do catch-all parameters, then every explicit parameter on DynamicComponent itself - now and in the future - effectively becomes a reserved word that you can’t pass to a dynamic child. It would become a breaking change to add any new parameters to DynamicComponent as they would start shadowing child component parameters that happen to have the same name … It’s unlikely that the call site knows of some fixed set of parameter names to pass to all possible dynamic children. So it’s going to be far more common to want to pass a dictionary.
Wrap up
In this post, we walked through the new DynamicComponent
, which allows you to render components when you don’t know your types at runtime. We were able to render a component based on what a user selects from a drop-down list. We also explored how to pass in parameters to the DynamicComponent
as well.