Understanding Parameters and EventCallbacks in Blazor
In Blazor, a component can receive information from its parent through parameters. Parameters are declared with the [Parameter] attribute, allowing a parent component to provide values such as text, numbers, dates, or Boolean values.
Blazor also supports EventCallback, which lets a child component notify its parent when a user performs an action. For example, a child can raise a callback after a button is clicked, while the parent decides what should happen next. This keeps reusable components focused on displaying information and reporting user actions.
The following two Razor components are provided separately. The code blocks are kept together without explanatory text between them.
@page "/parameters-demo" <h3>Parent Component</h3> <p>Message received: @receivedMessage</p> <ChildComponent Name="Ayush" OnMessageSent="HandleMessage" /> @code { private string receivedMessage = "No message received yet."; private void HandleMessage(string message) { receivedMessage = message; } } // GymCard.razor <div class="card gym-card h-100 shadow-sm"> <div class="card-body d-flex flex-column"> <div class="d-flex justify-content-between align-items-start gap-2 mb-3"> <h5 class="fw-bold mb-0">@GymName</h5> <span class="badge @(Status == "Active" ? "bg-success" : "bg-secondary")"> @Status </span> </div> <p class="gym-detail"> <i class="bi bi-geo-alt me-2"></i>@Address, @CityName </p> <p class="gym-detail"> <i class="bi bi-telephone me-2"></i>@Phone </p> <p class="gym-detail"> <i class="bi bi-envelope me-2"></i>@Email </p> <p class="gym-detail"> <i class="bi bi-clock me-2"></i> @OpeningTime.ToString(@"hh\:mm") - @ClosingTime.ToString(@"hh\:mm") </p> <p class="gym-detail"> <i class="bi bi-people me-2"></i> Class capacity: @TotalClassCapacity </p> <div class="d-flex flex-wrap gap-2 mb-3"> <span class="facility-badge"> Locker: @(LockerFacility ? "Yes" : "No") </span> <span class="facility-badge"> Parking: @(ParkingAvailable ? "Yes" : "No") </span> </div> <div class="d-flex gap-2 mt-auto"> <button type="button" class="btn btn-outline-primary btn-sm flex-fill" @onclick="EditGym"> <i class="bi bi-pencil me-1"></i>Edit </button> <button type="button" class="btn btn-outline-danger btn-sm flex-fill" @onclick="DeleteGym"> <i class="bi bi-trash me-1"></i>Delete </button> </div> </div> </div> @code { [Parameter] public Guid Id { get; set; } [Parameter] public string GymName { get; set; } = string.Empty; [Parameter] public string Address { get; set; } = string.Empty; [Parameter] public string CityName { get; set; } = string.Empty; [Parameter] public string Phone { get; set; } = string.Empty; [Parameter] public string Email { get; set; } = string.Empty; [Parameter] public TimeSpan OpeningTime { get; set; } [Parameter] public TimeSpan ClosingTime { get; set; } [Parameter] public int TotalClassCapacity { get; set; } [Parameter] public bool LockerFacility { get; set; } [Parameter] public bool ParkingAvailable { get; set; } [Parameter] public string Status { get; set; } = "Active"; [Parameter] public EventCallback<Guid> OnEdit { get; set; } [Parameter] public EventCallback<Guid> OnDelete { get; set; } private Task EditGym() => OnEdit.InvokeAsync(Id); private Task DeleteGym() => OnDelete.InvokeAsync(Id); } ========================================================================================= @page "/admin/gyms" @attribute [Microsoft.AspNetCore.Authorization.Authorize(Roles = "Admin")] @using System.Net.Http.Json @using System.ComponentModel.DataAnnotations @using Microsoft.AspNetCore.Components.Forms @using GymManagement.Client.Components.Admin @inject HttpClient Http @inject IJSRuntime JS <PageTitle>Manage Gyms</PageTitle> <div class="container-fluid py-4"> <div class="d-flex flex-wrap justify-content-between align-items-center gap-3 mb-4"> <div> <h2 class="fw-bold mb-1">Manage Gyms</h2> <p class="text-secondary mb-0">Add, update, search, and manage gyms.</p> </div> <button class="btn btn-primary" @onclick="OpenAddForm"> <i class="bi bi-plus-circle me-1"></i>Add Gym </button> </div> <div class="card shadow-sm border-0 mb-4"> <div class="card-body"> <div class="row g-3"> <div class="col-12 col-md-8"> <label class="form-label">Search gyms</label> <input class="form-control" @bind="searchText" @bind:event="oninput" placeholder="Search name, city, phone, or email..." /> </div> <div class="col-12 col-md-4"> <label class="form-label">Sort by</label> <select class="form-select" @bind="sortBy"> <option value="name">Gym name</option> <option value="city">City</option> <option value="status">Status</option> </select> </div> </div> </div> </div> @if (isLoading) { <div class="text-center py-5"> <div class="spinner-border text-primary"></div> <p class="text-secondary mt-2">Loading gyms...</p> </div> } else if (!string.IsNullOrWhiteSpace(errorMessage)) { <div class="alert alert-danger"> @errorMessage <button class="btn btn-sm btn-outline-danger ms-2" @onclick="LoadGymsAsync">Retry</button> </div> } else if (FilteredGyms.Count == 0) { <div class="alert alert-info">No matching gyms found.</div> } else { <div class="row g-4"> @foreach (var gym in FilteredGyms) { <div class="col-12 col-md-6 col-xl-4" @key="gym.Id"> <GymCard Id="@gym.Id" GymName="@gym.GymName" Address="@gym.Address" CityName="@gym.CityName" Phone="@gym.Phone" Email="@gym.Email" OpeningTime="@gym.OpeningTime" ClosingTime="@gym.ClosingTime" TotalClassCapacity="@gym.TotalClassCapacity" LockerFacility="@gym.LockerFacility" ParkingAvailable="@gym.ParkingAvailable" Status="@gym.Status" OnEdit="OpenEditForm" OnDelete="DeleteGymAsync" /> </div> } </div> } </div> @if (showForm) { <div class="modal-backdrop-custom"> <div class="card modal-card shadow-lg"> <div class="card-header bg-white d-flex justify-content-between align-items-center"> <h5 class="mb-0">@(isEditMode ? "Edit Gym" : "Add Gym")</h5> <button class="btn-close" @onclick="CloseForm"></button> </div> <div class="card-body"> <EditForm Model="@formModel" OnValidSubmit="SaveGymAsync"> <DataAnnotationsValidator /> <ValidationSummary /> <div class="row g-3"> <div class="col-md-6"> <label class="form-label">Gym name</label> <InputText class="form-control" @bind-Value="formModel.GymName" /> <ValidationMessage For="@(() => formModel.GymName)" /> </div> <div class="col-md-6"> <label class="form-label">City</label> <InputText class="form-control" @bind-Value="formModel.CityName" /> <ValidationMessage For="@(() => formModel.CityName)" /> </div> <div class="col-12"> <label class="form-label">Address</label> <InputText class="form-control" @bind-Value="formModel.Address" /> <ValidationMessage For="@(() => formModel.Address)" /> </div> <div class="col-md-6"> <label class="form-label">Phone</label> <InputText class="form-control" @bind-Value="formModel.Phone" /> <ValidationMessage For="@(() => formModel.Phone)" /> </div> <div class="col-md-6"> <label class="form-label">Email</label> <InputText class="form-control" @bind-Value="formModel.Email" /> <ValidationMessage For="@(() => formModel.Email)" /> </div> <div class="col-md-6"> <label class="form-label">Opening time</label> <InputText type="time" class="form-control" @bind-Value="formModel.OpeningTime" /> </div> <div class="col-md-6"> <label class="form-label">Closing time</label> <InputText type="time" class="form-control" @bind-Value="formModel.ClosingTime" /> </div> <div class="col-md-6"> <label class="form-label">Total class capacity</label> <InputNumber class="form-control" @bind-Value="formModel.TotalClassCapacity" /> <ValidationMessage For="@(() => formModel.TotalClassCapacity)" /> </div> <div class="col-md-6"> <label class="form-label">Status</label> <InputSelect class="form-select" @bind-Value="formModel.Status"> <option value="Active">Active</option> <option value="Inactive">Inactive</option> </InputSelect> </div> <div class="col-md-6 form-check ms-2"> <InputCheckbox class="form-check-input" @bind-Value="formModel.LockerFacility" /> <label class="form-check-label">Locker facility</label> </div> <div class="col-md-6 form-check ms-2"> <InputCheckbox class="form-check-input" @bind-Value="formModel.ParkingAvailable" /> <label class="form-checkSource:https://dev.to/striver_soren/understanding-parameters-and-eventcallbacks-in-blazor-1khhPreviousAutomated DevSecOps: Implementing SAST & Secret Detection in GitLab CI/CDNextMy favourite manual espresso machine of 2026 is now available with a huge 43% discount — there’s just one minor catch
Related posts

The Effort to Reach: Designing for Fitts’s Law
0dev.to UX
GitHub’s New Dependabot Verdict Can Lag Behind Your Next Commit
0dev.to GitHub

Document Review With Unsiloed and TypeSafe Jev
0dev.to Machine Learning
AmeriHealth Caritas Files 61-Worker WARN Notice in Orlando, Effective December 31, 2026
0dev.to Career
Remote SWE Jobs Paying Up to $220k (Nov 2)
0dev.to Career
What are your goals for the week? #203
0dev.to Career