komponenty šablony ASP.NET Core Blazor
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Autor: Robert Haken
Tento článek vysvětluje, jak můžou šablonované komponenty přijmout jednu nebo více šablon uživatelského rozhraní jako parametry, které se pak dají použít jako součást logiky vykreslování komponenty.
Komponenty bez vizuálního vzhledu
Šablonované komponenty jsou komponenty, které přijímají jednu nebo více šablon uživatelského rozhraní jako parametry, které je možné využít v logice vykreslování komponenty. Pomocí šablonovaných komponent můžete vytvářet komponenty vyšší úrovně, které jsou opakovaně použitelné. Příkladem může být:
- Komponenta tabulky, která uživateli umožňuje zadat šablony pro záhlaví, řádky a zápatí tabulky.
- Součást seznamu, která uživateli umožňuje zadat šablonu pro vykreslování položek v seznamu.
- Součást navigačního panelu, která uživateli umožňuje zadat šablonu pro spouštěcí obsah a navigační odkazy.
Šablona komponent je definována zadáním jednoho nebo více parametrů komponenty typu RenderFragment nebo RenderFragment<TValue>. Fragment vykreslení představuje segment uživatelského rozhraní, které se má vykreslit. RenderFragment<TValue> přebírá parametr typu, který lze zadat při vyvolání fragmentu vykreslení.
Poznámka:
Další informace o RenderFragmentkomponentách ASP.NET CoreRazor.
Šablonované komponenty jsou často obecně napsané, jak ukazuje následující TemplatedNavBar
komponenta (TemplatedNavBar.razor
). Obecný typ (<T>
) v následujícím příkladu slouží k vykreslení IReadOnlyList<T> hodnot, což je v tomto případě seznam domácích zvířat pro komponentu, která zobrazuje navigační panel s odkazy na komponentu podrobností domácího mazlíčka.
TemplatedNavBar.razor
:
@typeparam TItem
<nav class="navbar navbar-expand navbar-light bg-light">
<div class="container justify-content-start">
@StartContent
<div class="navbar-nav">
@foreach (var item in Items)
{
@ItemTemplate(item)
}
</div>
</div>
</nav>
@code {
[Parameter]
public RenderFragment? StartContent { get; set; }
[Parameter, EditorRequired]
public RenderFragment<TItem> ItemTemplate { get; set; } = default!;
[Parameter, EditorRequired]
public IReadOnlyList<TItem> Items { get; set; } = default!;
}
@typeparam TItem
<nav class="navbar navbar-expand navbar-light bg-light">
<div class="container justify-content-start">
@StartContent
<div class="navbar-nav">
@foreach (var item in Items)
{
@ItemTemplate(item)
}
</div>
</div>
</nav>
@code {
[Parameter]
public RenderFragment? StartContent { get; set; }
[Parameter, EditorRequired]
public RenderFragment<TItem> ItemTemplate { get; set; } = default!;
[Parameter, EditorRequired]
public IReadOnlyList<TItem> Items { get; set; } = default!;
}
@typeparam TItem
<nav class="navbar navbar-expand navbar-light bg-light">
<div class="container justify-content-start">
@StartContent
<div class="navbar-nav">
@foreach (var item in Items)
{
@ItemTemplate(item)
}
</div>
</div>
</nav>
@code {
[Parameter]
public RenderFragment? StartContent { get; set; }
[Parameter, EditorRequired]
public RenderFragment<TItem> ItemTemplate { get; set; } = default!;
[Parameter, EditorRequired]
public IReadOnlyList<TItem> Items { get; set; } = default!;
}
@typeparam TItem
<nav class="navbar navbar-expand navbar-light bg-light">
<div class="container justify-content-start">
@StartContent
<div class="navbar-nav">
@foreach (var item in Items)
{
@ItemTemplate(item)
}
</div>
</div>
</nav>
@code {
[Parameter]
public RenderFragment? StartContent { get; set; }
[Parameter, EditorRequired]
public RenderFragment<TItem> ItemTemplate { get; set; } = default!;
[Parameter, EditorRequired]
public IReadOnlyList<TItem> Items { get; set; } = default!;
}
@typeparam TItem
<nav class="navbar navbar-expand navbar-light bg-light">
<div class="container justify-content-start">
@StartContent
<div class="navbar-nav">
@foreach (var item in Items)
{
@ItemTemplate(item)
}
</div>
</div>
</nav>
@code {
[Parameter]
public RenderFragment StartContent { get; set; }
[Parameter]
public RenderFragment<TItem> ItemTemplate { get; set; } = default;
[Parameter]
public IReadOnlyList<TItem> Items { get; set; } = default;
}
@typeparam TItem
<nav class="navbar navbar-expand navbar-light bg-light">
<div class="container justify-content-start">
@StartContent
<div class="navbar-nav">
@foreach (var item in Items)
{
@ItemTemplate(item)
}
</div>
</div>
</nav>
@code {
[Parameter]
public RenderFragment StartContent { get; set; }
[Parameter]
public RenderFragment<TItem> ItemTemplate { get; set; } = default;
[Parameter]
public IReadOnlyList<TItem> Items { get; set; } = default;
}
Při použití šablonované komponenty lze parametry šablony zadat pomocí podřízených prvků, které odpovídají názvům parametrů. V následujícím příkladu <StartContent>...</StartContent>
a <ItemTemplate>...</ItemTemplate>
zadejte RenderFragment<TValue> šablony pro StartContent
a ItemTemplate
komponentu TemplatedNavBar
.
Context
Zadejte atribut elementu komponenty, pokud chcete zadat název parametru obsahu pro implicitní podřízený obsah (bez zabalení podřízeného elementu). V následujícím příkladu Context
se atribut zobrazí v elementu TemplatedNavBar
a vztahuje se na všechny RenderFragment<TValue> parametry šablony.
Pets1.razor
:
@page "/pets-1"
<PageTitle>Pets 1</PageTitle>
<h1>Pets Example 1</h1>
<TemplatedNavBar Items="pets" Context="pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}?ReturnUrl=%2Fpets-1")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-1"
<PageTitle>Pets 1</PageTitle>
<h1>Pets Example 1</h1>
<TemplatedNavBar Items="pets" Context="pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}?ReturnUrl=%2Fpets-1")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-1"
<PageTitle>Pets 1</PageTitle>
<h1>Pets Example 1</h1>
<TemplatedNavBar Items="pets" Context="pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}?ReturnUrl=%2Fpets-1")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-1"
<PageTitle>Pets 1</PageTitle>
<h1>Pets Example 1</h1>
<TemplatedNavBar Items="pets" Context="pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-1"
<h1>Pets Example 1</h1>
<TemplatedNavBar Items="pets" Context="pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
@page "/pets-1"
<h1>Pets Example 1</h1>
<TemplatedNavBar Items="pets" Context="pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Případně můžete změnit název parametru pomocí atributu Context
podřízeného elementu RenderFragment<TValue> . V následujícím příkladu Context
je nastavena spíše ItemTemplate
než TemplatedNavBar
.
Pets2.razor
:
@page "/pets-2"
<PageTitle>Pets 2</PageTitle>
<h1>Pets Example 2</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate Context="pet">
<NavLink href="@($"/pet-detail/{pet.PetId}?ReturnUrl=%2Fpets-2")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-2"
<PageTitle>Pets 2</PageTitle>
<h1>Pets Example 2</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate Context="pet">
<NavLink href="@($"/pet-detail/{pet.PetId}?ReturnUrl=%2Fpets-2")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-2"
<PageTitle>Pets 2</PageTitle>
<h1>Pets Example 2</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate Context="pet">
<NavLink href="@($"/pet-detail/{pet.PetId}?ReturnUrl=%2Fpets-2")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-2"
<PageTitle>Pets 2</PageTitle>
<h1>Pets Example 2</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate Context="pet">
<NavLink href="@($"/pet-detail/{pet.PetId}")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-2"
<h1>Pets Example 2</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate Context="pet">
<NavLink href="@($"/pet-detail/{pet.PetId}")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
@page "/pets-2"
<h1>Pets Example 2</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate Context="pet">
<NavLink href="@($"/pet-detail/{pet.PetId}")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Argumenty komponenty typu RenderFragment<TValue> mají implicitní parametr s názvem context
, který lze použít. V následujícím příkladu Context
není nastavená. @context.{PROPERTY}
poskytuje hodnoty domácích mazlíčků do šablony, kde {PROPERTY}
je Pet
vlastnost:
Pets3.razor
:
@page "/pets-3"
<PageTitle>Pets 3</PageTitle>
<h1>Pets Example 3</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{context.PetId}?ReturnUrl=%2Fpets-3")" class="nav-link">
@context.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-3"
<PageTitle>Pets 3</PageTitle>
<h1>Pets Example 3</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{context.PetId}?ReturnUrl=%2Fpets-3")" class="nav-link">
@context.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-3"
<PageTitle>Pets 3</PageTitle>
<h1>Pets Example 3</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{context.PetId}?ReturnUrl=%2Fpets-3")" class="nav-link">
@context.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-3"
<PageTitle>Pets 3</PageTitle>
<h1>Pets Example 3</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{context.PetId}")" class="nav-link">
@context.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-3"
<h1>Pets Example 3</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{context.PetId}")" class="nav-link">
@context.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
@page "/pets-3"
<h1>Pets Example 3</h1>
<TemplatedNavBar Items="pets">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{context.PetId}")" class="nav-link">
@context.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Pokud je to možné, při použití obecných komponent se parametr typu odvodí. Můžete však explicitně zadat typ s atributem, který má název odpovídající parametru typu, který je TItem
v předchozím příkladu:
Pets4.razor
:
@page "/pets-4"
<PageTitle>Pets 4</PageTitle>
<h1>Pets Example 4</h1>
<TemplatedNavBar Items="pets" Context="pet" TItem="Pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}?ReturnUrl=%2Fpets-4")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@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; }
}
}
@page "/pets-4"
<PageTitle>Pets 4</PageTitle>
<h1>Pets Example 4</h1>
<TemplatedNavBar Items="pets" Context="pet" TItem="Pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}?ReturnUrl=%2Fpets-4")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@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; }
}
}
@page "/pets-4"
<PageTitle>Pets 4</PageTitle>
<h1>Pets Example 4</h1>
<TemplatedNavBar Items="pets" Context="pet" TItem="Pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}?ReturnUrl=%2Fpets-4")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@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; }
}
}
@page "/pets-4"
<PageTitle>Pets 4</PageTitle>
<h1>Pets Example 4</h1>
<TemplatedNavBar Items="pets" Context="pet" TItem="Pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@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; }
}
}
@page "/pets-4"
<h1>Pets Example 4</h1>
<TemplatedNavBar Items="pets" Context="pet" TItem="Pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@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; }
}
}
@page "/pets-4"
<h1>Pets Example 4</h1>
<TemplatedNavBar Items="pets" Context="pet" TItem="Pet">
<StartContent>
<a href="/" class="navbar-brand">PetsApp</a>
</StartContent>
<ItemTemplate>
<NavLink href="@($"/pet-detail/{pet.PetId}")" class="nav-link">
@pet.Name
</NavLink>
</ItemTemplate>
</TemplatedNavBar>
@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; }
}
}
Příklad uvedený v komponentě TemplatedNavBar
(TemplatedNavBar.razor
) předpokládá, že Items
se kolekce po počátečním vykreslení nezmění, nebo že pokud se změní, není nutné zachovat stav komponent nebo prvků použitých v ItemTemplate
. Pro šablonované komponenty, u kterých se takové využití nedá očekávat, najdete v části Zachování vztahů s oddílem @key
.
Zachování relací s využitím @key
Šablonované komponenty se často používají k vykreslení kolekcí položek, jako jsou tabulky nebo seznamy. V takovýchobecnýchch Items
U těchto šablonovaných komponent je nutné zachovat vztahy s atributem direktivy @key
.
Poznámka:
Další informace o atributu @key
direktivy naleznete v tématu Zachovat element, komponentu a relace modelu v ASP.NET Core Blazor.
Následující TableTemplate
komponenta (TableTemplate.razor
) ukazuje šablonu komponentu, která zachovává vztahy s @key
.
TableTemplate.razor
:
@typeparam TItem
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
<tr @key="@item">@RowTemplate(item)</tr>
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment? TableHeader { get; set; }
[Parameter, EditorRequired]
public RenderFragment<TItem> RowTemplate { get; set; } = default!;
[Parameter, EditorRequired]
public IReadOnlyList<TItem> Items { get; set; } = default!;
}
@typeparam TItem
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
<tr @key="@item">@RowTemplate(item)</tr>
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment? TableHeader { get; set; }
[Parameter, EditorRequired]
public RenderFragment<TItem> RowTemplate { get; set; } = default!;
[Parameter, EditorRequired]
public IReadOnlyList<TItem> Items { get; set; } = default!;
}
@typeparam TItem
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
<tr @key="@item">@RowTemplate(item)</tr>
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment? TableHeader { get; set; }
[Parameter, EditorRequired]
public RenderFragment<TItem> RowTemplate { get; set; } = default!;
[Parameter, EditorRequired]
public IReadOnlyList<TItem> Items { get; set; } = default!;
}
@typeparam TItem
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
<tr @key="@item">@RowTemplate(item)</tr>
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment? TableHeader { get; set; }
[Parameter, EditorRequired]
public RenderFragment<TItem> RowTemplate { get; set; } = default!;
[Parameter, EditorRequired]
public IReadOnlyList<TItem> Items { get; set; } = default!;
}
@typeparam TItem
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
<tr @key="@item">@RowTemplate(item)</tr>
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment TableHeader { get; set; }
[Parameter]
public RenderFragment<TItem> RowTemplate { get; set; } = default;
[Parameter]
public IReadOnlyList<TItem> Items { get; set; } = default;
}
@typeparam TItem
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
<tr @key="@item">@RowTemplate(item)</tr>
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment TableHeader { get; set; }
[Parameter]
public RenderFragment<TItem> RowTemplate { get; set; } = default;
[Parameter]
public IReadOnlyList<TItem> Items { get; set; } = default;
}
Vezměte v úvahu následující Pets5
komponentu (Pets5.razor
), která demonstruje důležitost klíčových dat pro zachování relací modelu. Každá iterace přidání domácího mazlíčka v OnAfterRenderAsync
této komponentě vede k Blazor opětovnému vyřazuje komponentu TableTemplate
.
Pets5.razor
:
@page "/pets-5"
<PageTitle>Pets 5</PageTitle>
<h1>Pets Example 5</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td><input value="@pet.PetId" /></td>
<td><input value="@pet.Name" /></td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Insert new pet every 5 seconds
if (pets.Count < 10)
{
await Task.Delay(5000);
pets.Insert(0, new Pet() { PetId = pets.Count + 1, Name = "<new pet>" });
StateHasChanged();
}
}
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-5"
<PageTitle>Pets 5</PageTitle>
<h1>Pets Example 5</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td><input value="@pet.PetId" /></td>
<td><input value="@pet.Name" /></td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Insert new pet every 5 seconds
if (pets.Count < 10)
{
await Task.Delay(5000);
pets.Insert(0, new Pet() { PetId = pets.Count + 1, Name = "<new pet>" });
StateHasChanged();
}
}
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-5"
<PageTitle>Pets 5</PageTitle>
<h1>Pets Example 5</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td><input value="@pet.PetId" /></td>
<td><input value="@pet.Name" /></td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Insert new pet every 5 seconds
if (pets.Count < 10)
{
await Task.Delay(5000);
pets.Insert(0, new Pet() { PetId = pets.Count + 1, Name = "<new pet>" });
StateHasChanged();
}
}
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-5"
<PageTitle>Pets 5</PageTitle>
<h1>Pets Example 5</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td><input value="@pet.PetId" /></td>
<td><input value="@pet.Name" /></td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Insert new pet every 5 seconds
if (pets.Count < 10)
{
await Task.Delay(5000);
pets.Insert(0, new Pet() { PetId = pets.Count + 1, Name = "<new pet>" });
StateHasChanged();
}
}
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}
@page "/pets-5"
<h1>Pets Example 5</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td><input value="@pet.PetId" /></td>
<td><input value="@pet.Name" /></td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Insert new pet every 5 seconds
if (pets.Count < 10)
{
await Task.Delay(5000);
pets.Insert(0, new Pet() { PetId = pets.Count + 1, Name = "<new pet>" });
StateHasChanged();
}
}
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
@page "/pets-5"
<h1>Pets Example 5</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td><input value="@pet.PetId" /></td>
<td><input value="@pet.Name" /></td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 1, Name = "Mr. Bigglesworth" },
new Pet { PetId = 2, Name = "Salem Saberhagen" },
new Pet { PetId = 3, Name = "K-9" }
};
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Insert new pet every 5 seconds
if (pets.Count < 10)
{
await Task.Delay(5000);
pets.Insert(0, new Pet() { PetId = pets.Count + 1, Name = "<new pet>" });
StateHasChanged();
}
}
private class Pet
{
public int PetId { get; set; }
public string Name { get; set; }
}
}
Tato ukázka umožňuje:
<input>
Vyberte z několika vykreslených řádků tabulky.- Prostudujte chování fokusu stránky při automatickém růstu kolekce domácích zvířat.
Bez použití atributu @key
direktivy v TableTemplate
komponentě zůstane fokus stránky na stejné pozici indexu (řádek) tabulky, což způsobí přesun fokusu při každém přidání domácího mazlíčka. Chcete-li to předvést, odeberte @key
atribut a hodnotu direktivy, restartujte aplikaci a pokuste se upravit hodnotu pole při přidání položek.