ASP.NET Core Blazor templated components
This article explains how templated components can accept one or more UI templates as parameters, which can then be used as part of the component's rendering logic.
Templated components are components that accept one or more UI templates as parameters, which can then be used as part of the component's rendering logic. Templated components allow you to author higher-level components that are more reusable than regular components. A couple of examples include:
- A table component that allows a user to specify templates for the table's header, rows, and footer.
- A list component that allows a user to specify a template for rendering items in a list.
A templated component is defined by specifying one or more component parameters of type RenderFragment or RenderFragment<TValue>. A render fragment represents a segment of UI to render. RenderFragment<TValue> takes a type parameter that can be specified when the render fragment is invoked.
Note
For more information on RenderFragment, see ASP.NET Core Razor components.
Often, templated components are generically typed, as the following TableTemplate
component demonstrates. The generic type <T>
in this example is used to render IReadOnlyList<T>
values, which in this case is a series of pet rows in a component that displays a table of pets.
Shared/TableTemplate.razor
:
@typeparam TItem
@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; }
}
When using a templated component, the template parameters can be specified using child elements that match the names of the parameters. In the following example, <TableHeader>...</TableHeader>
and <RowTemplate>...<RowTemplate>
supply RenderFragment<TValue> templates for TableHeader
and RowTemplate
of the TableTemplate
component.
Specify the Context
attribute on the component element when you want to specify the content parameter name for implicit child content (without any wrapping child element). In the following example, the Context
attribute appears on the TableTemplate
element and applies to all RenderFragment<TValue> template parameters.
Pages/Pets1.razor
:
@page "/pets1"
<h1>Pets</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
Alternatively, you can change the parameter name using the Context
attribute on the RenderFragment<TValue> child element. In the following example, the Context
is set on RowTemplate
rather than TableTemplate
:
Pages/Pets2.razor
:
@page "/pets2"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate Context="pet">
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
Component arguments of type RenderFragment<TValue> have an implicit parameter named context
, which can be used. In the following example, Context
isn't set. @context.{PROPERTY}
supplies pet values to the template, where {PROPERTY}
is a Pet
property:
Pages/Pets3.razor
:
@page "/pets3"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
When using generic-typed components, the type parameter is inferred if possible. However, you can explicitly specify the type with an attribute that has a name matching the type parameter, which is TItem
in the preceding example:
Pages/Pets4.razor
:
@page "/pets4"
<h1>Pets</h1>
<TableTemplate Items="pets" TItem="Pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
Additional resources
Templated components are components that accept one or more UI templates as parameters, which can then be used as part of the component's rendering logic. Templated components allow you to author higher-level components that are more reusable than regular components. A couple of examples include:
- A table component that allows a user to specify templates for the table's header, rows, and footer.
- A list component that allows a user to specify a template for rendering items in a list.
A templated component is defined by specifying one or more component parameters of type RenderFragment or RenderFragment<TValue>. A render fragment represents a segment of UI to render. RenderFragment<TValue> takes a type parameter that can be specified when the render fragment is invoked.
Note
For more information on RenderFragment, see ASP.NET Core Razor components.
Often, templated components are generically typed, as the following TableTemplate
component demonstrates. The generic type <T>
in this example is used to render IReadOnlyList<T>
values, which in this case is a series of pet rows in a component that displays a table of pets.
Shared/TableTemplate.razor
:
@typeparam TItem
@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; }
}
When using a templated component, the template parameters can be specified using child elements that match the names of the parameters. In the following example, <TableHeader>...</TableHeader>
and <RowTemplate>...<RowTemplate>
supply RenderFragment<TValue> templates for TableHeader
and RowTemplate
of the TableTemplate
component.
Specify the Context
attribute on the component element when you want to specify the content parameter name for implicit child content (without any wrapping child element). In the following example, the Context
attribute appears on the TableTemplate
element and applies to all RenderFragment<TValue> template parameters.
Pages/Pets1.razor
:
@page "/pets1"
<h1>Pets</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
Alternatively, you can change the parameter name using the Context
attribute on the RenderFragment<TValue> child element. In the following example, the Context
is set on RowTemplate
rather than TableTemplate
:
Pages/Pets2.razor
:
@page "/pets2"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate Context="pet">
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
Component arguments of type RenderFragment<TValue> have an implicit parameter named context
, which can be used. In the following example, Context
isn't set. @context.{PROPERTY}
supplies pet values to the template, where {PROPERTY}
is a Pet
property:
Pages/Pets3.razor
:
@page "/pets3"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
When using generic-typed components, the type parameter is inferred if possible. However, you can explicitly specify the type with an attribute that has a name matching the type parameter, which is TItem
in the preceding example:
Pages/Pets4.razor
:
@page "/pets4"
<h1>Pets</h1>
<TableTemplate Items="pets" TItem="Pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
Additional resources
Templated components are components that accept one or more UI templates as parameters, which can then be used as part of the component's rendering logic. Templated components allow you to author higher-level components that are more reusable than regular components. A couple of examples include:
- A table component that allows a user to specify templates for the table's header, rows, and footer.
- A list component that allows a user to specify a template for rendering items in a list.
A templated component is defined by specifying one or more component parameters of type RenderFragment or RenderFragment<TValue>. A render fragment represents a segment of UI to render. RenderFragment<TValue> takes a type parameter that can be specified when the render fragment is invoked.
Note
For more information on RenderFragment, see ASP.NET Core Razor components.
Often, templated components are generically typed, as the following TableTemplate
component demonstrates. The generic type <T>
in this example is used to render IReadOnlyList<T>
values, which in this case is a series of pet rows in a component that displays a table of pets.
Shared/TableTemplate.razor
:
@typeparam TItem
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
<tr>@RowTemplate(item)</tr>
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment TableHeader { get; set; }
[Parameter]
public RenderFragment<TItem> RowTemplate { get; set; }
[Parameter]
public IReadOnlyList<TItem> Items { get; set; }
}
When using a templated component, the template parameters can be specified using child elements that match the names of the parameters. In the following example, <TableHeader>...</TableHeader>
and <RowTemplate>...<RowTemplate>
supply RenderFragment<TValue> templates for TableHeader
and RowTemplate
of the TableTemplate
component.
Specify the Context
attribute on the component element when you want to specify the content parameter name for implicit child content (without any wrapping child element). In the following example, the Context
attribute appears on the TableTemplate
element and applies to all RenderFragment<TValue> template parameters.
Pages/Pets1.razor
:
@page "/pets1"
<h1>Pets</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Alternatively, you can change the parameter name using the Context
attribute on the RenderFragment<TValue> child element. In the following example, the Context
is set on RowTemplate
rather than TableTemplate
:
Pages/Pets2.razor
:
@page "/pets2"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate Context="pet">
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Component arguments of type RenderFragment<TValue> have an implicit parameter named context
, which can be used. In the following example, Context
isn't set. @context.{PROPERTY}
supplies pet values to the template, where {PROPERTY}
is a Pet
property:
Pages/Pets3.razor
:
@page "/pets3"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
When using generic-typed components, the type parameter is inferred if possible. However, you can explicitly specify the type with an attribute that has a name matching the type parameter, which is TItem
in the preceding example:
Pages/Pets4.razor
:
@page "/pets4"
<h1>Pets</h1>
<TableTemplate Items="pets" TItem="Pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Additional resources
Templated components are components that accept one or more UI templates as parameters, which can then be used as part of the component's rendering logic. Templated components allow you to author higher-level components that are more reusable than regular components. A couple of examples include:
- A table component that allows a user to specify templates for the table's header, rows, and footer.
- A list component that allows a user to specify a template for rendering items in a list.
A templated component is defined by specifying one or more component parameters of type RenderFragment or RenderFragment<TValue>. A render fragment represents a segment of UI to render. RenderFragment<TValue> takes a type parameter that can be specified when the render fragment is invoked.
Note
For more information on RenderFragment, see ASP.NET Core Razor components.
Often, templated components are generically typed, as the following TableTemplate
component demonstrates. The generic type <T>
in this example is used to render IReadOnlyList<T>
values, which in this case is a series of pet rows in a component that displays a table of pets.
Shared/TableTemplate.razor
:
@typeparam TItem
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
<tr>@RowTemplate(item)</tr>
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment TableHeader { get; set; }
[Parameter]
public RenderFragment<TItem> RowTemplate { get; set; }
[Parameter]
public IReadOnlyList<TItem> Items { get; set; }
}
When using a templated component, the template parameters can be specified using child elements that match the names of the parameters. In the following example, <TableHeader>...</TableHeader>
and <RowTemplate>...<RowTemplate>
supply RenderFragment<TValue> templates for TableHeader
and RowTemplate
of the TableTemplate
component.
Specify the Context
attribute on the component element when you want to specify the content parameter name for implicit child content (without any wrapping child element). In the following example, the Context
attribute appears on the TableTemplate
element and applies to all RenderFragment<TValue> template parameters.
Pages/Pets1.razor
:
@page "/pets1"
<h1>Pets</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new List<Pet>
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Alternatively, you can change the parameter name using the Context
attribute on the RenderFragment<TValue> child element. In the following example, the Context
is set on RowTemplate
rather than TableTemplate
:
Pages/Pets2.razor
:
@page "/pets2"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate Context="pet">
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new List<Pet>
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Component arguments of type RenderFragment<TValue> have an implicit parameter named context
, which can be used. In the following example, Context
isn't set. @context.{PROPERTY}
supplies pet values to the template, where {PROPERTY}
is a Pet
property:
Pages/Pets3.razor
:
@page "/pets3"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new List<Pet>
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
When using generic-typed components, the type parameter is inferred if possible. However, you can explicitly specify the type with an attribute that has a name matching the type parameter, which is TItem
in the preceding example:
Pages/Pets4.razor
:
@page "/pets4"
<h1>Pets</h1>
<TableTemplate Items="pets" TItem="Pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new List<Pet>
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Additional resources
Feedback
Submit and view feedback for