Descriere Generală
FODInputRadio
și FODInputRadioGroup
formează sistemul de butoane radio pentru FOD.Components. Sistemul oferă două moduri de afișare (radio clasic și butoane), suport pentru binding bidirecțional, validare integrată cu EditForm și localizare automată pentru enum-uri.
Utilizare de Bază
<!-- Radio group simplu -->
<FODInputRadioGroup @bind-Value="selectedOption"
Options="@options"
Label="Selectați o opțiune" />
<!-- Radio group cu enum -->
<FODInputRadioGroup @bind-Value="status"
Label="Status"
Options="@GetEnumOptions<OrderStatus>()" />
<!-- Radio buttons stil butoane -->
<FODInputRadioGroup @bind-Value="size"
Type="FodRadioType.Button"
Label="Dimensiune"
Options="@sizeOptions" />
@code {
private string selectedOption;
private OrderStatus status;
private string size = "M";
private List<SelectableItem<string>> options = new()
{
new("opt1", "Opțiunea 1"),
new("opt2", "Opțiunea 2"),
new("opt3", "Opțiunea 3")
};
private List<SelectableItem<string>> sizeOptions = new()
{
new("S", "Small"),
new("M", "Medium"),
new("L", "Large"),
new("XL", "Extra Large")
};
}
Atribute Disponibile
Atribut |
Tip |
Default |
Descriere |
Value |
T |
- |
Valoarea selectată |
Options |
IEnumerable> |
- |
Lista de opțiuni |
Label |
string |
- |
Eticheta grupului |
Type |
FodRadioType |
Radio |
Tipul afișării (Radio/Button) |
Disable |
bool |
false |
Dezactivează toate opțiunile |
Required |
bool |
false |
Câmp obligatoriu |
BoldText |
bool |
false |
Text îngroșat pentru label |
LabelFontSize |
int |
0 |
Dimensiune font label |
InputFontSize |
int |
0 |
Dimensiune font input |
ValueExpression |
Expression> |
- |
Expresie pentru validare |
ValueChanged |
EventCallback |
- |
Eveniment la schimbare |
For |
Expression> |
- |
Expresie pentru EditForm |
Atribut |
Tip |
Default |
Descriere |
Item |
SelectableItem |
- |
Elementul reprezentat |
Disable |
bool |
false |
Dezactivează opțiunea |
Label |
string |
- |
Label personalizat |
LabelFontSize |
int |
0 |
Dimensiune font label |
InputFontSize |
int |
0 |
Dimensiune font input |
Evenimente
Eveniment |
Tip |
Descriere |
ValueChanged |
EventCallback |
Declanșat la selectare opțiune |
OnClick |
EventCallback |
Click pe radio button |
Metode Publice
Metodă |
Returnează |
Descriere |
GetName() |
string |
Returnează numele grupului |
SetSelectedValue(T) |
Task |
Setează valoarea selectată |
TryGetValue() |
string |
Obține valoarea curentă ca string |
Tipuri și Enum-uri
FodRadioType
public enum FodRadioType
{
Radio, // Butoane radio clasice
Button // Afișare ca grup de butoane
}
SelectableItem
public class SelectableItem<T>
{
public string Value { get; set; } // Valoarea internă
public string Text { get; set; } // Textul afișat
public T Data { get; set; } // Obiectul asociat
public SelectableItem(T data, string text)
{
Data = data;
Value = data?.ToString();
Text = text;
}
}
Exemple Avansate
Radio Group cu Enum Localizat
<FODInputRadioGroup @bind-Value="priority"
Label="Prioritate"
Options="@GetLocalizedEnumOptions<Priority>()"
Required="true" />
@code {
private Priority priority = Priority.Normal;
public enum Priority
{
[Display(Name = "Priority_Low", ResourceType = typeof(Resources.Enums))]
Low,
[Display(Name = "Priority_Normal", ResourceType = typeof(Resources.Enums))]
Normal,
[Display(Name = "Priority_High", ResourceType = typeof(Resources.Enums))]
High,
[Display(Name = "Priority_Urgent", ResourceType = typeof(Resources.Enums))]
Urgent
}
private List<SelectableItem<Priority>> GetLocalizedEnumOptions<TEnum>()
where TEnum : Enum
{
return Enum.GetValues<TEnum>()
.Select(e => new SelectableItem<TEnum>((TEnum)(object)e, GetEnumDisplayName(e)))
.ToList();
}
}
<style>
.custom-radio-group .fod-radio-button-group {
gap: 10px;
}
.custom-radio-group .btn-check:checked + .btn {
background-color: var(--fod-primary);
color: white;
border-color: var(--fod-primary);
}
.custom-radio-group .btn {
min-width: 100px;
padding: 10px 20px;
border-radius: 25px;
}
</style>
<div class="custom-radio-group">
<FODInputRadioGroup @bind-Value="selectedPlan"
Type="FodRadioType.Button"
Label="Selectați planul"
Options="@planOptions" />
</div>
@code {
private string selectedPlan = "standard";
private List<SelectableItem<string>> planOptions = new()
{
new("basic", "Basic - 10 MDL"),
new("standard", "Standard - 25 MDL"),
new("premium", "Premium - 50 MDL")
};
}
Radio Group cu Validare Personalizată
<EditForm Model="@model" OnValidSubmit="@HandleSubmit">
<DataAnnotationsValidator />
<FODInputRadioGroup @bind-Value="model.DeliveryMethod"
For="@(() => model.DeliveryMethod)"
Label="Metoda de livrare"
Options="@deliveryOptions"
Required="true" />
@if (model.DeliveryMethod == "courier")
{
<FodInput @bind-Value="model.Address"
Label="Adresa de livrare"
Required="true" />
}
<ValidationSummary />
<FodButton Type="submit">Continuă</FodButton>
</EditForm>
@code {
private OrderModel model = new();
private List<SelectableItem<string>> deliveryOptions = new()
{
new("pickup", "Ridicare personală"),
new("courier", "Livrare prin curier"),
new("post", "Poșta Moldovei")
};
private class OrderModel
{
[Required(ErrorMessage = "Selectați metoda de livrare")]
public string DeliveryMethod { get; set; }
public string Address { get; set; }
}
}
<FODInputRadioGroup @bind-Value="selectedService"
Label="Tip serviciu"
Options="@serviceOptions">
<ChildContent>
@foreach (var service in services)
{
<FODInputRadio Item="@GetServiceItem(service)" T="string">
<span>@service.Name</span>
@if (!string.IsNullOrEmpty(service.Description))
{
<Tooltip Text="@service.Description">
<FodIcon Icon="info" Size="FodSize.Small" />
</Tooltip>
}
<br/>
<small class="text-muted">@service.Price.ToString("C")</small>
</FODInputRadio>
}
</ChildContent>
</FODInputRadioGroup>
@code {
private string selectedService;
private List<Service> services = new()
{
new() { Id = "express", Name = "Express", Price = 50, Description = "Livrare în 24h" },
new() { Id = "standard", Name = "Standard", Price = 25, Description = "Livrare în 3-5 zile" },
new() { Id = "economy", Name = "Economic", Price = 10, Description = "Livrare în 7-10 zile" }
};
}
Radio Group Dinamic
<FODInputRadioGroup @bind-Value="selectedCategory"
Label="Categorie"
Options="@categoryOptions"
ValueChanged="@OnCategoryChanged" />
@if (subcategoryOptions?.Any() == true)
{
<FODInputRadioGroup @bind-Value="selectedSubcategory"
Label="Subcategorie"
Options="@subcategoryOptions" />
}
@code {
private string selectedCategory;
private string selectedSubcategory;
private List<SelectableItem<string>> categoryOptions;
private List<SelectableItem<string>> subcategoryOptions;
protected override async Task OnInitializedAsync()
{
categoryOptions = await LoadCategories();
}
private async Task OnCategoryChanged(string newCategory)
{
selectedSubcategory = null;
subcategoryOptions = await LoadSubcategories(newCategory);
}
}
Integrare cu On Behalf Of
<FODInputRadioOnBehalfOf @bind-Value="model.RequestType"
Label="Depun cererea"
ShowOnBehalfOfOption="true"
OnBehalfOfLabel="În numele altei persoane"
PersonalLabel="Pentru mine" />
@if (model.RequestType == RequestType.OnBehalfOf)
{
<FodInput @bind-Value="model.PersonName"
Label="Numele persoanei"
Required="true" />
<FodInput @bind-Value="model.PersonIDNP"
Label="IDNP"
Required="true"
Pattern="[0-9]{13}" />
}
@code {
private RequestModel model = new();
public enum RequestType
{
Personal,
OnBehalfOf
}
}
Componente Asociate
FODInputWrapper
- Container pentru elemente de formular
FODSelectableFormComponent<T>
- Clasă de bază pentru componente cu selecție
ValidationMessage
- Afișare mesaje de validare
Stilizare
Clase CSS
.form-check
.form-check-input
.form-check-label
.btn-check
.btn
.fod-radio-button-group
Personalizare Aspect
/* Radio buttons personalizate */
.form-check-input[type="radio"] {
width: 20px;
height: 20px;
border: 2px solid var(--fod-primary);
}
.form-check-input[type="radio"]:checked {
background-color: var(--fod-primary);
border-color: var(--fod-primary);
}
/* Button group personalizat */
.fod-radio-button-group .btn {
border-radius: 20px;
padding: 8px 24px;
margin: 0 5px;
}
.fod-radio-button-group .btn-check:checked + .btn {
background-color: var(--fod-primary);
color: white;
transform: scale(1.05);
}
Note și Observații
- Generic Type - Suportă orice tip T care poate fi convertit în string
- Enum Support - Suport automat pentru Display attributes
- Localization - Integrare cu IStringLocalizer pentru traduceri
- Validation - Funcționează cu DataAnnotations și EditForm
- Accessibility - Generează ID-uri unice pentru label association
Bune Practici
- Folosiți
For
pentru integrare corectă cu EditForm
- Definiți
Display
attributes pentru enum-uri localizate
- Limitați numărul de opțiuni la 5-7 pentru usability
- Folosiți tipul Button pentru opțiuni puține și clare
- Adăugați descrieri pentru opțiuni complexe
- Grupați opțiunile logic când sunt multe
- Setați o valoare implicită când e posibil
Concluzie
FODInputRadio oferă o implementare flexibilă și puternică pentru selecția unei singure opțiuni din mai multe. Cu suport pentru două moduri de afișare, localizare automată și integrare completă cu sistemul de validare Blazor, componenta acoperă majoritatea scenariilor de selecție unică în formulare.