Blazor Development Standards
Use these standards when writing Blazor components in the ProcurementHub project.
Component Library Priority
Only relevant if the corresponding library is already included in the project.
- •WssBlazorControls - Primary choice for forms and inputs. Also reference edit-controls.md for detailed usage.
- •AntBlazor - Limited to: Modal, Multiselect, Popconfirm, Notification
- •Native HTML - When EditControls are insufficient
Form Controls
razor
<!-- Primary Controls --> <EditString @bind-Value="model.Name" Field="@(() => model.Name)" /> <EditTextArea @bind-Value="model.Description" Field="@(() => model.Description)" /> <EditNumber @bind-Value="model.Amount" Field="@(() => model.Amount)" Format="C" /> <EditBool @bind-Value="model.IsActive" Field="@(() => model.IsActive)" /> <EditDate @bind-Value="model.Date" Field="@(() => model.Date)" /> <EditSelectEnum @bind-Value="model.Status" Field="@(() => model.Status)" Type="typeof(Status)" /> <!-- Specialized Controls --> <EditBoolNullRadio @bind-Value="model.IsApproved" Field="@(() => model.IsApproved)" /> <EditRadioEnum @bind-Value="model.Priority" Field="@(() => model.Priority)" Type="typeof(Priority)" /> <EditCheckedStringList @bind-Value="model.Tags" Field="@(() => model.Tags)" Options="tagOptions" />
Layout Patterns
razor
<!-- Vertical Layout -->
<div class="flex-column-16">
<EditString @bind-Value="model.Name" Field="@(() => model.Name)" />
<EditTextArea @bind-Value="model.Description" Field="@(() => model.Description)" />
</div>
<!-- Horizontal Layout -->
<div class="flex-row-16">
<EditString @bind-Value="model.FirstName" Field="@(() => model.FirstName)" />
<EditString @bind-Value="model.LastName" Field="@(() => model.LastName)" />
</div>
<!-- Accessible Form Groups (6+ fields or complex forms) -->
<fieldset class="card flex-column-16">
<legend>Contact Information</legend>
<EditString @bind-Value="model.Email" Field="@(() => model.Email)" />
<EditString @bind-Value="model.Phone" Field="@(() => model.Phone)" />
</fieldset>
Component Code Organization
Code-Behind Pattern (Use [Inject] Properties, NOT Constructor Injection)
csharp
// Component.razor.cs - Keep logic separate from markup
namespace ProcurementHub.Client.Components;
public partial class Component
{
[Inject] MyService MyService { get; set; } = null!;
[Parameter] public Model Data { get; set; } = new();
[Parameter] public bool IsReadOnly { get; set; }
async Task HandleSubmit()
{
// Business logic here
}
}
Two-Way Binding Pattern
csharp
public partial class CustomInput
{
[Parameter] public string Value { get; set; } = string.Empty;
[Parameter] public EventCallback<string> ValueChanged { get; set; }
async Task OnValueChanged(string newValue)
{
Value = newValue;
await ValueChanged.InvokeAsync(Value);
}
}
Blazor Best Practices Checklist
- •✅ Single-file components - Combine
.razorand.razor.cswhen total < 60 lines; only separate when ≥ 60 lines or complex logic - •✅ Code-behind files - Separate
.razor.csfor logic when combined.razorfile would exceed 60 lines; combine for smaller components - •✅ [Inject] properties - Use
[Inject]for dependency injection, NOT constructor injection - •✅ EditControls first - Use WssBlazorControls before alternatives
- •✅ Two-way binding - Implement
@bind-Valuepattern for custom components - •✅ Use existing CSS - Check app.css, edit-controls.css, ant-overrides.css first
- •✅ Consistent spacing -
flex-column-16vertical,flex-row-16horizontal - •✅ CSS isolation - Component-specific styles in
.razor.cssfiles - •✅ Accessibility - Use
fieldset/legendfor form groups (6+ fields or complex forms) - •✅ Concise markup - Use ternary operators and helper methods
- •✅ Method groups - Use
@onclick="Toggle"instead of lambda wrappers - •✅ Avoid code in markup - Keep logic in code-behind files
- •✅ Comment nested sections - Add comments <!-- --> for nested markup
- •✅ Remove unnecessary parameters - Only pass what is needed to child components
- •✅ Remove unnecessary nesting - If a div and it's parent div can be combined, do so.
- •❌ Constructor injection - Use
[Inject]properties instead for Blazor components