Læringsmål
- Definere
[Parameter]og forældre/child-kommunikation. - Bruge
@bindog@bind-Value:aftertil two-way data. - Implementere
EventCallbacktil events opad (valgt champion). - Sammenligne Blazor-events med jQuery/DOM-manipulation.
Hvornår opdele i komponenter? Når samme UI gentages (Pokémon-kort, LoL-række) eller når parent skal koordinere state (valgt id + detail-panel) uden 200 linjer Razor i én fil.
Tjek dig selv før du går videre
- Du kan forklare EventCallback vs Action med parent/child-eksempel.
- Du ved hvorfor child ikke må mutere [Parameter] direkte.
- Du har brugt bind-lab og forstår two-way flow.
Komponenter er Blazors byggeklodser. En fil = én komponent (typisk). Parent sender data ned; child notifier op via callbacks.
Two-way binding preview
Skriv trænernavn — preview opdateres som ved @bind.
Valgt træner: —
Parametre og EventCallback
Parent ↔ child
Klik kortet eller Afspil — se EventCallback gå op, mens parametre går ned.
@* PokemonCard.razor *@
<div class="card" @onclick="OnSelect">
<h3>@Name</h3>
<p>#@Id</p>
</div>
@code {
[Parameter] public string Name { get; set; } = "";
[Parameter] public int Id { get; set; }
[Parameter] public EventCallback<int> Selected { get; set; }
private async Task OnSelect() => await Selected.InvokeAsync(Id);
}
@* PokemonList.razor (parent) *@
@foreach (var p in mons)
{
<PokemonCard Name="@p.Name" Id="@p.Id" Selected="OnPick" />
}
<p>Valgt id: @selectedId</p>
@code {
int? selectedId;
List<Mon> mons = ...;
private Task OnPick(int id)
{
selectedId = id;
return Task.CompletedTask;
}
record Mon(string Name, int Id);
}
EventCallback vs EventCallback<T>: Uden payload når parent bare skal reagere («luk modal»). Med int / string når child sender id (Pokémon #25, champion «Ahri»). Parent ejer konsekvensen — fx await Lol.GetChampionAsync(id).
Cascading parameters (kort): når mange børn skal kende samme «valgt træner» eller tema uden at hver PokemonCard får 10 parametre — se livscyklus-lektionen; events opad er stadig primary for valg-handlinger.
@bind dybere
@bind-Value="text" er syntaks-sukker for value + ValueChanged + ValueExpression. Til delayed API-søgning kan I bruge @bind-Value:after="Search" (.NET 8+) så søgning kører efter opdatering.
<input @bind="filter" @bind:event="oninput" />
@bind:event="oninput" opdaterer ved hvert tastetryk (default er often onchange ved blur).
Hvornår @bind-Value:after? LoL-filter der kalder OpgaverAPI efter tekstfelt opdateres — undgå at kalde API inde i set på property; lad Blazor færdiggøre bind, derefter søg.
<input @bind="filter" @bind:event="oninput" @bind:after="SearchAsync" />
C# vs JavaScript
- Objekter & klasser — stærke typer på parametre
- Events —
@onclick,@onchange; stop propagation med@onclick:stopPropagation - DOM — undgå manuel query; beskriv UI fra state
- JS interop —
IJSRuntimenår browser-API mangler
Faldgrube: At mutere child’s [Parameter] direkte i child — one-way flow ned, events op. Parent ejer sandheden om selectedId.
Genbrug i større UI
Samme ChampionRow i LoL-liste og i «favoritter»-sidebar — kun parametre og callbacks skifter.
Trin ved refaktorering: udtræk markup → tilføj [Parameter] → erstat hardcoded klik med EventCallback → parent injecter service og henter API-data.
Quiz 1
Hvordan sender child «jeg blev valgt» til parent?
Quiz 2
Hvad gør @bind-Value i praksis?
EventCallback vs Action
Hvorfor det betyder noget: Når ChampionRow melder valg opad, skal parent opdatere selectedId og måske hente detail fra OpgaverAPI. EventCallback sørger for korrekt re-render og kan await’es; Action gør ikke.
// Svagt i Blazor-komponenter
[Parameter] public Action<int> OnPick { get; set; } = _ => { };
// Korrekt — async-friendly og render-aware
[Parameter] public EventCallback<int> OnPick { get; set; }
private Task PickAsync() => OnPick.InvokeAsync(ChampionId);
Parent kan await’e og hente LoL-detail før UI vises:
private async Task OnChampionPicked(int id)
{
selectedId = id;
detail = await Lol.GetChampionAsync(id);
}
Sådan fejler det i praksis (@bind): Parent binder @bind-SelectedId på child, men child sætter også SelectedId = id i onclick — state kæmper, UI «hopper tilbage». Parent ejer bound property; child bruger EventCallback eller lader @bind håndtere Changed-kanalen alene.
@* Anti-pattern: child skriver til parent's parameter *@
@code {
[Parameter] public int SelectedId { get; set; }
void BadClick(int id) => SelectedId = id; // undgå — brug EventCallback eller @bind-SelectedId
}
Mini-opgave
ChampionRow med EventCallback<string>; parent holder selectedId og henter detail fra OpgaverAPI ved valg.
Quiz 3
Notify parent om valg?
Læs hos Microsoft
Prøv med API
- Byg
PokemonCardog genbrug på liste fra Pokémon-demo. - Parent viser detail-panel når
EventCallbackfyrer.
Baseret på MAGS Blazor-wiki og Microsoft Learn — Blazor.