Component Basics at a Glance
A Razor component file (.razor) mixes HTML-like markup with C# in an @code block; the file name becomes the component's tag name, so Counter.razor is used as <Counter />, and a routable page adds an @page directive with a route template such as @page "/counter". Parameters are declared with the [Parameter] attribute on a public property, and a parent passes values as attributes matching the property name, while child-to-parent communication uses an EventCallback<T> parameter that the child invokes with InvokeAsync when something happens.
Cricket analogy: A player's specific batting position in the order (opener, middle order, finisher) determines how they're used in the lineup, just as a component's file name determines its tag name and how it's placed in the markup.
Common Directives Reference
@bind creates two-way data binding on form elements, defaulting to the oninput event for text inputs (or use @bind:event="onchange" to bind on blur instead), and @bind-Value with @bind-Value:event is the pattern used for binding to a component's own [Parameter] property. @onclick, @onchange, and other @on{event} directives wire up DOM event handlers to C# methods, @if/@else if/@else and @foreach work exactly like their C# counterparts inside markup, and @ref captures a reference to a DOM element or child component instance for direct manipulation, most commonly used to call methods on a child component or pass an ElementReference into JS interop.
Cricket analogy: A two-way radio between the dressing room and the field lets instructions flow both directions instantly, mirroring @bind synchronizing a variable both from the UI to the code and back.
Lifecycle and Data Binding Reference
For forms, wrap fields in an EditForm bound to a model with Model="@myModel" or an explicit EditContext, add validation with <DataAnnotationsValidator /> and display errors with <ValidationSummary /> or <ValidationMessage For="@(() => myModel.Field)" />, and handle submission with OnValidSubmit or OnValidSubmitAsync, which only fires when validation passes. Dependency injection uses @inject ServiceType ServiceName at the top of a component to get a property-injected instance from the DI container, and any component implementing IDisposable (or IAsyncDisposable) has its Dispose/DisposeAsync method called automatically when the component is removed from the render tree, which is the correct place to unsubscribe from events or dispose timers and subscriptions.
Cricket analogy: A match only proceeds to the presentation ceremony once the umpires have signed off on a valid result, mirroring OnValidSubmit only firing once validation passes.
@* Component with parameter, event callback, and lifecycle *@
@page "/counter"
<h3>Count: @count</h3>
<button @onclick="Increment">+</button>
@code {
[Parameter] public int InitialValue { get; set; }
[Parameter] public EventCallback<int> OnCountChanged { get; set; }
private int count;
protected override void OnInitialized() => count = InitialValue;
private async Task Increment()
{
count++;
await OnCountChanged.InvokeAsync(count);
}
}
@* Form with validation *@
<EditForm Model="@order" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText @bind-Value="order.CustomerName" />
<button type="submit">Place Order</button>
</EditForm>
@inject IOrderService OrderService
@code {
private Order order = new();
private async Task HandleValidSubmit() => await OrderService.SubmitAsync(order);
}Quick lifecycle order to memorize: SetParametersAsync -> OnInitialized/OnInitializedAsync (once) -> OnParametersSet/OnParametersSetAsync (every update) -> render -> OnAfterRender/OnAfterRenderAsync(firstRender) -> subsequent updates re-enter at OnParametersSet.
@bind on a text input defaults to the oninput event, updating on every keystroke; if you need the value only after the user leaves the field, explicitly set @bind:event="onchange", otherwise you may trigger far more re-renders than intended on a large form.
- A component's filename becomes its tag name; @page adds a routable URL.
- [Parameter] properties receive values from a parent; EventCallback<T> sends events back up.
- @bind is two-way and defaults to oninput for text; use @bind:event="onchange" to bind on blur instead.
- @ref captures a reference to a DOM element or child component instance for direct access.
- EditForm + DataAnnotationsValidator + OnValidSubmit only invokes the handler after validation passes.
- @inject property-injects a service from DI at the top of a component.
- Implement IDisposable/IAsyncDisposable to clean up subscriptions and timers when a component leaves the render tree.
Practice what you learned
1. What determines the tag name used to reference a Razor component elsewhere in the app?
2. By default, which DOM event does @bind use for a text input?
3. What is @ref used for in a Blazor component?
4. When does EditForm's OnValidSubmit handler get invoked?
5. Where should you unsubscribe from an event or dispose a timer that a component set up?
Was this page helpful?
You May Also Like
Blazor Best Practices
Practical guidelines for structuring components, managing state, and keeping Blazor apps fast and maintainable in production.
Blazor Interview Questions
Commonly asked Blazor interview questions covering render modes, component lifecycle, state management, JS interop, and performance, with clear answers.
Testing Blazor Components with bUnit
Learn how to write fast, reliable unit tests for Blazor components using bUnit, from rendering and interaction to mocking dependencies.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics