blazor-components
Blazor Component Model
Render Modes (.NET 10 Blazor Web App)
The unified Blazor Web App model supports four render modes:
Static Server-Side Rendering (SSR)
- Default mode, no
@rendermodedirective - HTML rendered on server, sent as static HTML
- No interactivity (no event handlers)
- Best for: content pages, SEO-critical pages, fast initial load
@page "/about"
@attribute [StreamRendering] @* Enable streaming for async data *@
<h1>About Us</h1>
<p>@_content</p>
@code {
private string? _content;
protected override async Task OnInitializedAsync()
{
_content = await ContentService.GetAboutAsync();
}
}
Interactive Server
@rendermode InteractiveServer- Uses SignalR WebSocket connection
- Server processes UI events, sends diffs to client
- Best for: admin dashboards, real-time data, forms with server validation
Interactive WebAssembly
@rendermode InteractiveWebAssembly- .NET runtime runs in browser via WebAssembly
- No server connection needed after initial download
- Best for: offline-capable apps, client-heavy processing
Interactive Auto
@rendermode InteractiveAuto- First render uses Server mode (fast start)
- Switches to WebAssembly once runtime is downloaded
- Best for: public apps needing both fast start and offline capability
Component Lifecycle
Constructor → SetParametersAsync → OnInitialized[Async] → OnParametersSet[Async]
→ BuildRenderTree → OnAfterRender[Async](firstRender: true)
Parameter change → SetParametersAsync → OnParametersSet[Async]
→ BuildRenderTree → OnAfterRender[Async](firstRender: false)
Disposal → Dispose/DisposeAsync
Key Rules
OnInitializedAsyncruns once - use for initial data loadingOnParametersSetAsyncruns on every parameter change - use for dependent dataOnAfterRenderAsyncruns after DOM update - use for JS interop- Always check
firstRenderinOnAfterRenderAsyncto avoid duplicate JS calls
Component Communication
Parent to Child (Parameters)
@* Parent *@
<ChildComponent Title="Hello" Items="@_items" OnDelete="HandleDelete" />
@* Child *@
@code {
[Parameter] public string Title { get; set; } = "";
[Parameter] public List<Item> Items { get; set; } = [];
[Parameter] public EventCallback<int> OnDelete { get; set; }
}
Child to Parent (EventCallback)
@* Child *@
<button @onclick="() => OnDelete.InvokeAsync(item.Id)">Delete</button>
Cascading Values (ancestor to all descendants)
@* Layout or parent *@
<CascadingValue Value="@_theme" Name="AppTheme">
@Body
</CascadingValue>
@* Any descendant *@
@code {
[CascadingParameter(Name = "AppTheme")] public Theme? Theme { get; set; }
}
State Container (cross-component via DI)
public sealed class AppState
{
public event Action? OnChange;
private int _count;
public int Count => _count;
public void Increment()
{
_count++;
OnChange?.Invoke();
}
}
// Register as Scoped (Server) or Singleton (WASM)
Forms and Validation
<EditForm Model="@_model" OnValidSubmit="HandleSubmit" FormName="my-form">
<DataAnnotationsValidator />
<InputText @bind-Value="_model.Name" />
<ValidationMessage For="@(() => _model.Name)" />
<InputNumber @bind-Value="_model.Quantity" />
<InputDate @bind-Value="_model.DueDate" />
<InputSelect @bind-Value="_model.Category">
@foreach (var cat in _categories)
{
<option value="@cat">@cat</option>
}
</InputSelect>
<button type="submit">Save</button>
</EditForm>
Razor Directive Ordering Convention (from official docs)
@page "/doctor-who-episodes/{season:int}"
@rendermode InteractiveWebAssembly
@using System.Globalization
@using BlazorSample.Components.Layout
@attribute [Authorize]
@implements IAsyncDisposable
@inject IJSRuntime JS
@inject ILogger<DoctorWhoEpisodes> Logger
<PageTitle>Doctor Who Episode List</PageTitle>
Prerendering Control (from official docs)
@* Disable prerender for specific component *@
@rendermode @(new InteractiveServerRenderMode(prerender: false))
@* Disable for entire app in App.razor *@
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
@* Handle client-only services during prerender *@
@code {
protected override void OnInitialized()
{
// Check if service exists (null during server prerender)
if (Services.GetService<IWebAssemblyHostEnvironment>() is { } env)
environmentName = env.Environment;
}
}
State Management (from official docs)
// State container service
public class StateContainer
{
private string? savedString;
public string Property
{
get => savedString ?? string.Empty;
set { savedString = value; NotifyStateChanged(); }
}
public event Action? OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
}
// Register: AddScoped (Server), AddSingleton (WASM)
@implements IDisposable
@inject StateContainer StateContainer
<p>@StateContainer.Property</p>
@code {
protected override void OnInitialized() =>
StateContainer.OnChange += StateHasChanged;
public void Dispose() =>
StateContainer.OnChange -= StateHasChanged;
}
Component Naming Conventions (from official docs)
- Component names must start with uppercase:
ProductDetail.razor(notproductDetail.razor) - File paths use PascalCase:
Components/Pages/ProductDetail.razor - Routable URLs use kebab-case:
@page "/product-detail" - Namespace resolution:
@namespacedirective >RootNamespacein csproj > project namespace + folder path
Partial Class Pattern (from official docs)
@* CounterPartialClass.razor *@
@page "/counter-partial-class"
<button @onclick="IncrementCount">Click me</button>
<p>Count: @currentCount</p>
// CounterPartialClass.razor.cs
namespace BlazorSample.Components.Pages;
public partial class CounterPartialClass
{
private int currentCount = 0;
private void IncrementCount() => currentCount++;
}
Key Patterns
- Use
@keyon repeated elements for efficient diffing - Use
<Virtualize>for large lists (renders only visible items) - Use
[SupplyParameterFromQuery]for query string binding - Use
[SupplyParameterFromForm]for form model binding in SSR - Use
NavigationManager.NavigateTo()for programmatic navigation - Use
IDisposableto unsubscribe from events - Use
ErrorBoundaryto catch component-level errors gracefully - Component names must start uppercase (enforced by compiler)
- Use partial classes to separate markup from logic
More from lobbi-docs/claude
vision-multimodal
Vision and multimodal capabilities for Claude including image analysis, PDF processing, and document understanding. Activate for image input, base64 encoding, multiple images, and visual analysis.
250design-system
Apply and manage the AI-powered design system with 50+ curated styles
126complex-reasoning
Multi-step reasoning patterns and frameworks for systematic problem solving. Activate for Chain-of-Thought, Tree-of-Thought, hypothesis-driven debugging, and structured analytical approaches that leverage extended thinking.
106gcp
Google Cloud Platform services including GKE, Cloud Run, Cloud Storage, BigQuery, and Pub/Sub. Activate for GCP infrastructure, Google Cloud deployment, and GCP integration.
73kanban
Kanban methodology including boards, WIP limits, flow metrics, and continuous delivery. Activate for Kanban boards, workflow visualization, and lean project management.
63debugging
Debugging techniques for Python, JavaScript, and distributed systems. Activate for troubleshooting, error analysis, log investigation, and performance debugging. Includes extended thinking integration for complex debugging scenarios.
59