Components
A component is a reusable part of the UI, created using a .razor file.
Hello Blazor
Welcome to my application.
Every component can contain HTML, C# logic, and event handlers.
Examples: Navbar, Login form, Product list, Dashboard
- Data Binding Data binding connects UI elements with C# variables.
<input @bind="name" /> <p>Your name: @name</p> @code { private string name = ""; } Event Handling
Handles user actions such as clicks and form submissions.
razor
<button @onclick="Increment">Click</button> <p>Count: @count</p> @code { private int count; private void Increment() { count++; } } Front-End ├── Components/ │ └── Admin/ │ ├── GymCard.razor │ └── GymForm.razor │ └── Pages/ └── Admin/ └── ManageGyms.razor ==================================================================== GymForm.razor @using Microsoft.AspNetCore.Components.Forms @using System.ComponentModel.DataAnnotations <EditForm Model="@Model" OnValidSubmit="@SubmitAsync"> <DataAnnotationsValidator /> <ValidationSummary class="text-danger mb-3" /> <div class="row g-3"> <div class="col-md-6"> <label class="form-label">Gym Name</label> <InputText class="form-control" @bind-Value="Model.GymName" /> <ValidationMessage For="@(() => Model.GymName)" /> </div> <div class="col-md-6"> <label class="form-label">City</label> <InputText class="form-control" @bind-Value="Model.CityName" /> <ValidationMessage For="@(() => Model.CityName)" /> </div> <div class="col-12"> <label class="form-label">Address</label> <InputText class="form-control" @bind-Value="Model.Address" /> <ValidationMessage For="@(() => Model.Address)" /> </div> <div class="col-md-6"> <label class="form-label">Phone</label> <InputText class="form-control" @bind-Value="Model.Phone" /> <ValidationMessage For="@(() => Model.Phone)" /> </div> <div class="col-md-6"> <label class="form-label">Email</label> <InputText class="form-control" @bind-Value="Model.Email" /> <ValidationMessage For="@(() => Model.Email)" /> </div> <div class="col-md-6"> <label class="form-label">Opening Time</label> <InputText type="time" class="form-control" @bind-Value="Model.OpeningTime" /> <ValidationMessage For="@(() => Model.OpeningTime)" /> </div> <div class="col-md-6"> <label class="form-label">Closing Time</label> <InputText type="time" class="form-control" @bind-Value="Model.ClosingTime" /> <ValidationMessage For="@(() => Model.ClosingTime)" /> </div> <div class="col-md-6"> <label class="form-label">Total Class Capacity</label> <InputNumber class="form-control" @bind-Value="Model.TotalClassCapacity" /> <ValidationMessage For="@(() => Model.TotalClassCapacity)" /> </div> <div class="col-md-6"> <label class="form-label">Status</label> <InputSelect class="form-select" @bind-Value="Model.Status"> <option value="Active">Active</option> <option value="Inactive">Inactive</option> </InputSelect> <ValidationMessage For="@(() => Model.Status)" /> </div> <div class="col-md-6"> <div class="form-check"> <InputCheckbox class="form-check-input" @bind-Value="Model.LockerFacility" /> <label class="form-check-label"> Locker facility available </label> </div> </div> <div class="col-md-6"> <div class="form-check"> <InputCheckbox class="form-check-input" @bind-Value="Model.ParkingAvailable" /> <label class="form-check-label"> Parking available </label> </div> </div> </div> <div class="d-flex justify-content-end gap-2 mt-4"> <button type="button" class="btn btn-outline-secondary" disabled="@IsSaving" @onclick="CancelAsync"> Cancel </button> <button type="submit" class="btn btn-primary" disabled="@IsSaving"> @if (IsSaving) { <span class="spinner-border spinner-border-sm me-2"></span> } @(IsEditMode ? "Update Gym" : "Save Gym") </button> </div> </EditForm> @code { [Parameter, EditorRequired] public ManageGyms.GymFormModel Model { get; set; } = default!; [Parameter] public bool IsEditMode { get; set; } [Parameter] public bool IsSaving { get; set; } [Parameter] public EventCallback OnValidSubmit { get; set; } [Parameter] public EventCallback OnCancel { get; set; } private Task SubmitAsync() => OnValidSubmit.InvokeAsync(); private Task CancelAsync() => OnCancel.InvokeAsync(); } ========================================================================== GymCard.razor <div class="card gym-card h-100 shadow-sm border-0"> <div class="card-header bg-white border-0 pt-3"> <div class="d-flex justify-content-between gap-2"> <div> <h5 class="fw-bold mb-1">@GymName</h5> <div class="text-muted small"> <i class="bi bi-geo-alt me-1"> @Display(CityName) </div> </div> <span class="badge @(IsActive ? "text-bg-success" : "text-bg-secondary")"> @Status </span> </div> </div> <div class="card-body"> <div class="gym-detail"> <i class="bi bi-geo-alt-fill"> <span>@Display(Address)</span> </div> <div class="gym-detail"> <i class="bi bi-telephone-fill"> <span>@Display(Phone)</span> </div> <div class="gym-detail"> <i class="bi bi-envelope-fill"> <span class="gym-email">@Display(Email)</span> </div> <div class="gym-detail"> <i class="bi bi-clock-fill"> <span> @OpeningTime.ToString(@"hh\:mm") – @ClosingTime.ToString(@"hh\:mm") </span> </div> <div class="gym-detail"> <i class="bi bi-people-fill"> <span>Class capacity: @TotalClassCapacity</span> </div> <div class="gym-detail"> <i class="bi bi-lock-fill"> <span>Locker: @(LockerFacility ? "Available" : "Not available")</span> </div> <div class="gym-detail"> <i class="bi bi-car-front-fill"> <span>Parking: @(ParkingAvailable ? "Available" : "Not available")</span> </div> </div> <div class="card-footer bg-white border-0 pb-3"> <div class="d-flex flex-wrap gap-2"> <button type="button" class="btn btn-primary btn-sm flex-fill" @onclick="() => OnViewPlans.InvokeAsync(Id)"> <i class="bi bi-card-list me-1"> View Plans </button> <button type="button" class="btn btn-outline-secondary btn-sm" @onclick="() => OnEdit.InvokeAsync(Id)"> <i class="bi bi-pencil-square me-1"> Edit </button> <button type="button" class="btn btn-outline-danger btn-sm" @onclick="() => OnDelete.InvokeAsync(Id)"> <i class="bi bi-trash me-1"> Delete </button> </div> </div> </div> <style> .gym-card { border-radius: 12px; transition: transform .2s ease; } .gym-card:hover { transform: translateY(-3px); } .gym-detail { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 12px; overflow-wrap: anywhere; } .gym-detail > i { color: #0d6efd; min-width: 18px; margin-top: 3px; } .gym-email { overflow-wrap: anywhere; } @code { [Parameter] public Guid Id { get; set; } [Parameter] public string GymName { get; set; } = ""; [Parameter] public string Address { get; set; } = ""; [Parameter] public string CityName { get; set; } = ""; [Parameter] public string Phone { get; set; } = ""; [Parameter] public string Email { get; set; } = ""; [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; } [Parameter] public EventCallback<Guid> OnViewPlans { get; set; } private bool IsActive => string.Equals(Status, "Active", StringComparison.OrdinalIgnoreCase); private static string Display(string? value) => string.IsNullOrWhiteSpace(value) ? "Not provided" : value; } ================================================================ ManageGyms.razor (Admin) @page "/admin/gyms" @using System.Net.Http.Json @using System.ComponentModel.DataAnnotations @using Microsoft.AspNetCore.Authorization @using