Templated Component with RenderFragment in Blazor
What RenderFragment is and how to use it in an application will be covered in this blog. The component and content are rendered with the aid of the RenderFragment. Reusing the components is made easier by the templated component.
RenderFragment and RenderFragment<T> are the two different sorts of render elements.
RenderFragment - It is a just a simple razor content RenderFragment<T> - It allows parameters within the razor content. The context keyword helps to set a parameter within the razor content.
Let's start by looking at a simple RenderFragment example. The code for the child component is as follows. In this case, ChildContent is declared as RenderFragment. The UI segment is rendered by this RenderFragment. additionally, the @ChildContent is put within the <div> element.
Child.razor<div class="alert alert-primary">
@ChildContent
</div>
@code
{
[Parameter]
public RenderFragment? ChildContent { get; set; }
}
A parent component comes next. Here, the string "Have a nice day!" has been inserted inside the child component. That is a child component parameter.
Parent.razor<Child>
Have a nice day!
</Child>
The outcome of the preceding code is as follows. In this scenario, the parent component renders the child component along with a simple UI message (Have a nice day!).
Multiple Render Fragments
The following example will demonstrate how to pass multiple render fragments. FirstChildContent and SecondChildContent are two RenderFragements that are declared in the Child.razor code below. And inside the div element, the two Render Fragments are displayed.
Child.razor<div>First Child Content</div>
<div class="alert alert-primary">
@FirstChildContent
</div>
<div>Second Child Content</div>
<div class="alert alert-secondary">
@SecondChildContent
</div>
@code {
[Parameter]
public RenderFragment? FirstChildContent { get; set; }
[Parameter]
public RenderFragment? SecondChildContent { get; set; }
}
The following is a parent component. Here inside the <child> component <FirstChildContent> and <SecondChildContent> are added with is UI parameter.
Parent.razor<Child>
<FirstChildContent>
First Content: Have a nice day!
</FirstChildContent>
<SecondChildContent>
Second Content: Wishing you a great day!
</SecondChildContent>
</Child>
The code above produced the output below. You can see that the parent component is showing both child contents in this output.
Templated Component with Generically Type
Next, you're going to see how to pass generic values to template. Following is the TableTemplate component. To render a generic <T> value, an IReadOnlyList<TItem> items property is added. It will display the table rows. RenderFragment? TableHeader will provide the value to render the table header name. RenderFragment<TItem>? RowTemplate will provide table row values.
TableTemplate.razor@using System.Diagnostics.CodeAnalysis
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
if (RowTemplate is not null)
{
<tr>@RowTemplate(item)</tr>
}
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment? TableHeader { get; set; }
[Parameter]
public RenderFragment<TItem>? RowTemplate { get; set; }
[Parameter, AllowNull]
public IReadOnlyList<TItem> Items { get; set; }
}
The code below is the Table.razor component. It will display two tables with the same TableTemplate. The code has two classes Movie and Production. The Movie has three property variables ID, Name and ReleaseYear. And the Production has two property variables ID and Name. Values are initialized for both Movie and Production. And passed to TableTemplate
Table.razor<h4>Movies</h4>
<TableTemplate Items="Movies" Context="movie">
<TableHeader>
<th>ID</th>
<th>Name</th>
<th>Release Year</th>
</TableHeader>
<RowTemplate>
<td>@movie.ID</td>
<td>@movie.Name</td>
<td>@movie.ReleaseYear</td>
</RowTemplate>
</TableTemplate>
<h4>Productions</h4>
<TableTemplate Items="Productions" Context="prod">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@prod.ID</td>
<td>@prod.Name</td>
</RowTemplate></TableTemplate>
@code {
private List<Movie> Movies = new()
{
new Movie { ID =1, Name = "Frozen", ReleaseYear = 2013 },
new Movie { ID =2, Name = "Moana", ReleaseYear = 2016 },
new Movie { ID =3, Name = "Dumbo", ReleaseYear = 2019 }
};
private class Movie
{
public int ID { get; set; }
public string? Name { get; set; }
public int ReleaseYear { get; set; }
}
private List<Production> Productions = new()
{
new Production { ID =1, Name = "Pixar Animation Studios" },
new Production { ID =2, Name = "Marc Platt Productions" },
new Production { ID =3, Name = "Bardel Entertainment" }
};
private class Production
{
public int ID { get; set; }
public string? Name { get; set; }
}
}
The below image is an output of the above code. Here you can see both Movie and Production data are displayed with the same template.
Alternate ways to pass parameters
In the below example, the Context is added in <RowTemplate><TableHeader>
<th>ID</th>
<th>Name</th>
<th>Release Year</th>
</TableHeader>
<RowTemplate Context="movie">
<td>@movie.ID</td>
<td>@movie.Name</td>
<td>@movie.ReleaseYear</td>
</RowTemplate>
</TableTemplate>
RenderFragment<TValue> has a context parameter. So in the below example the Context is not set. Instead of that parameters are passed using RenderFragment<TValue>’s context (@context.{PROPERTY}).
<TableHeader>
<th>ID</th>
<th>Name</th>
<th>Release Year</th>
</TableHeader>
<RowTemplate>
<td>@context.ID</td>
<td>@context.Name</td>
<td>@context.ReleaseYear</td>
</RowTemplate>
</TableTemplate>
In the final method the TItem is specified explicitly.
<TableHeader>
<th>ID</th>
<th>Name</th>
<th>Release Year</th>
</TableHeader>
<RowTemplate>
<td>@context.ID</td>
<td>@context.Name</td>
<td>@context.ReleaseYear</td>
</RowTemplate>
</TableTemplate>
I hope this helps you. Keep coding.
Smooth and excellent explanation.
ReplyDeleteCould you please do more on this topic,
Thank you very much.
Thank you, I am happy to hear this
Delete