To generate dynamic components in Blazor, we commonly use RenderTreeBuilder
or the RenderFragment
To dynamically render a component. These require a lot of manual work, like maintaining the component’s visible status based on whether the component should be displayed or hidden, which is more difficult with complex data.
Beginning with .NET 6 Preview 1, the ASP.NET Core team introduced DynamicComponent . By using DynamicComponent, you can reduce the complexity of dynamic component rendering when dealing with large amounts of complex data.
If you are not using .net6 preview1 then you can achived the same thing without using the DynamicComponet. please refer the following article
Dynamically-rendered ASP.NET Core Blazor components
What is DynamicComponent?
DynamicComponent is a new built-in Blazor component that can be used to render dynamic components using its type and optional parameters.
Let’s understand this with an example. Suppose you want to show a to-do list as a list view
and a table view
As shown in the below image. You can quickly develop this functionality using. DynamicComponent.
Create two-component with different designs and then give the option to the user to select the view he is comfortable with.
Let’s dive into code. I assume you know how to create and run the blazor project. In the newly created blazor app, I have created two-component ListView.razor
and TableView.razor
and then populated the dropdown list with components.
On the main page, I have added the following code snippet I am creating a list of Component
with parameter name, type, and parameters(in our case, it is null), and then by setting the currently selected component to DynamicComponent
rest all the heavy lifting work is done by the DynamicComponent
<DynamicComponent Type="@(Type.GetType(currentComponent.Type))" Parameters="@currentComponent.Parameters"
/>
_Main.razor
<select @onchange="SelectView">
@foreach(var c in componentList){
<option value="@c.Name">@c.Name</option>
}
</select>
<DynamicComponent Type="@(Type.GetType(currentComponent.Type))" Parameters="@currentComponent.Parameters"
/>
@code {
private Component currentComponent { get; set; }
private List<Component> componentList=new List<Component>();
public class Component
{
public string Name { get; set; }
public string Type { get; set; }
public Dictionary<string, object> Parameters { get; set; }
}
protected override async Task OnInitializedAsync()
{
componentList = new List<Component>()
{
new Component() { Name = "ListView",Type = typeof(ListView).AssemblyQualifiedName,
Parameters = null},
new Component() { Name = "TableView",Type = typeof(TableView).AssemblyQualifiedName,
Parameters = null}
};
currentComponent = componentList[0];
await base.OnInitializedAsync();
}
public void SelectView(ChangeEventArgs e){
currentComponent = this.componentList.FirstOrDefault(x => x.Name.Equals(e.Value.ToString()));
}
}
# Complete Source Code
This file is a simple PCOC class for holding todo data
Todo.cs
namespace BlazorRepl.UserComponents
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class Todo
{
public int id { get; set; }
public string title { get; set; }
public bool completed { get; set; }
}
}
TodoService.cs
Fake service for returning a list of todos
namespace BlazorRepl.UserComponents
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;
using System.Net.Http;
using System.Text.Json.Serialization;
public class TodoService
{
private List<Todo> todos;
public List<Todo> GetData()
{
todos = new List<Todo>(){
new Todo{id=1,title="write the blog post",completed=false},
new Todo{id=2,title="go grocery outlet",completed=true},
new Todo{id=3,title="lreom ipsum",completed=true},
new Todo{id=4,title="lorem ipsum lorem ipsum",completed=false},
};
return todos;
}
}
}
TableView.razor
I am using bootstrap to create simple table
@inject TodoService todoService
<h1>TableView</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
<th scope="col">Completed</th>
</tr>
</thead>
<tbody>
@foreach(var todo in todoService.GetData()){
<tr>
<td>@todo.id</td>
<td>@todo.title</td>
<td>@todo.completed</td>
</tr>
}
</tbody>
</table>
ListView.razor
Bootstrap list group for showing todos as list-group
@inject TodoService todoService
<h1>List View</h1>
<ul class="list-group">
@foreach(var todo in todoService.GetData()){
<li class="list-group-item d-flex justify-content-between align-items-center">
<span>@todo.id</span> @todo.title
<p class="list-group-item-text text-success">
@todo.completed
</p>
</li>
}
</ul>
Demo
Click on preview and play with the demo