Radio
1. Descriere Generală
FODInputRadioGroup
și FODInputRadio
formează un sistem complet pentru implementarea butoanelor radio în formulare Blazor. Sistemul oferă două stiluri de afișare (radio tradițional și grup de butoane), suport pentru tipuri generice, validare integrată și localizare automată.
Caracteristici principale:
- Suport pentru enum-uri cu localizare automată
- Două stiluri vizuale: Radio și Button
- Binding bidirecțional cu validare
- Suport pentru surse de date personalizate
- Tooltips pentru descrieri detaliate
- Integrare completă cu sistemul de formulare Blazor
- Componente specializate pentru scenarii specifice (OnBehalfOf)
2. Ghid de Utilizare API
Radio group de bază cu enum
<EditForm Model="model" OnValidSubmit="HandleSubmit">
<DataAnnotationsValidator />
<FODInputRadioGroup T="PersonType"
@bind-Value="model.PersonType"
Label="Tip persoană" />
<ValidationMessage For="@(() => model.PersonType)" />
</EditForm>
@code {
public enum PersonType
{
[Display(Name = "Persoană fizică")]
Individual = 1,
[Display(Name = "Persoană juridică")]
LegalEntity = 2
}
public class FormModel
{
[Required(ErrorMessage = "Selectați tipul persoanei")]
public PersonType PersonType { get; set; }
}
}
Radio group stil butoane
<FODInputRadioGroup T="DeliveryOption"
@bind-Value="selectedDelivery"
Type="FodRadioType.Button"
Label="Modalitate de livrare">
</FODInputRadioGroup>
@code {
public enum DeliveryOption
{
[Display(Name = "Livrare electronică", Description = "Prin MDelivery")]
Electronic = 1,
[Display(Name = "Ridicare de la oficiu", Description = "Personal la sediu")]
Office = 2,
[Display(Name = "Livrare poștală", Description = "Prin Poșta Moldovei")]
Post = 3
}
private DeliveryOption selectedDelivery = DeliveryOption.Electronic;
}
Radio group cu date personalizate
<FODInputRadioGroup T="Office"
@bind-Value="selectedOffice"
Source="offices"
Label="Selectați oficiul" />
@code {
private Office selectedOffice;
private List<Office> offices = new()
{
new Office { Id = 1, Name = "Oficiul Central", Address = "str. Ștefan cel Mare 1" },
new Office { Id = 2, Name = "Oficiul Botanica", Address = "bd. Dacia 45" },
new Office { Id = 3, Name = "Oficiul Rîșcani", Address = "str. Kiev 15" }
};
public class Office
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
}
Radio group cu etichete personalizate
<FODInputRadioGroup T="PaymentMethod"
@bind-Value="model.PaymentMethod"
ItemLabels="GetPaymentLabels()"
Label="Metodă de plată" />
@code {
private IEnumerable<KeyValuePair<PaymentMethod, string>> GetPaymentLabels()
{
return new List<KeyValuePair<PaymentMethod, string>>
{
new(PaymentMethod.Card, "Card bancar (Visa/Mastercard)"),
new(PaymentMethod.MPay, "MPay - Plată guvernamentală"),
new(PaymentMethod.Cash, "Numerar la oficiu")
};
}
}
<FODInputRadioGroup T="ServiceType"
@bind-Value="selectedService"
Label="Tip serviciu">
</FODInputRadioGroup>
@code {
public enum ServiceType
{
[Display(Name = "Apostilă",
Description = "Legalizarea documentelor pentru utilizare internațională")]
Apostille = 1,
[Display(Name = "Traducere autorizată",
Description = "Traducere oficială cu ștampilă și semnătură")]
Translation = 2,
[Display(Name = "Copie legalizată",
Description = "Copie certificată conform originalului")]
CertifiedCopy = 3
}
}
Radio group cu validare
<EditForm Model="formData" OnValidSubmit="ProcessForm">
<DataAnnotationsValidator />
<FODInputRadioGroup T="RequestorType"
@bind-Value="formData.RequestorType"
Label="Depun solicitarea"
Type="FodRadioType.Button" />
<ValidationMessage For="@(() => formData.RequestorType)" />
@if (formData.RequestorType == RequestorType.OnBehalf)
{
<div class="mt-3">
<FODInputText @bind-Value="formData.AuthorizationNumber"
Label="Număr împuternicire"
Required="true" />
</div>
}
<FodButton Type="submit" Variant="FodVariant.Filled" Color="FodColor.Primary">
Continuă
</FodButton>
</EditForm>
@code {
public class FormData
{
[Required(ErrorMessage = "Selectați modul de depunere")]
public RequestorType RequestorType { get; set; }
public string AuthorizationNumber { get; set; }
}
public enum RequestorType
{
[Display(Name = "În nume propriu")]
Personal = 1,
[Display(Name = "În baza împuternicirii")]
OnBehalf = 2
}
}
Radio group dezactivat condiționat
<FODInputRadioGroup T="ProcessingSpeed"
@bind-Value="model.Speed"
Disable="@(!model.IsUrgent)"
Label="Termen de procesare">
</FODInputRadioGroup>
<FodCheckbox @bind-Checked="model.IsUrgent" Label="Procesare urgentă" />
@code {
public class Model
{
public ProcessingSpeed Speed { get; set; } = ProcessingSpeed.Normal;
public bool IsUrgent { get; set; }
}
public enum ProcessingSpeed
{
[Display(Name = "Normal (3 zile)")]
Normal = 1,
[Display(Name = "Rapid (1 zi)")]
Fast = 2,
[Display(Name = "Express (2 ore)")]
Express = 3
}
}
Componenta specializată OnBehalfOf
<FODInputOnBehalfOfRadioGroup @bind-Value="model.OnBehalfOf" />
@code {
private Model model = new();
public class Model
{
public OnBehalfOnEnum OnBehalfOf { get; set; } = OnBehalfOnEnum.Personal;
}
}
Radio group cu stilizare personalizată
<FODInputRadioGroup T="Theme"
@bind-Value="userTheme"
Type="FodRadioType.Button"
Label="Temă interfață"
BoldText="true"
LabelFontSize="16"
InputFontSize="14">
</FODInputRadioGroup>
@code {
public enum Theme
{
[Display(Name = "🌞 Luminoasă")]
Light = 1,
[Display(Name = "🌙 Întunecată")]
Dark = 2,
[Display(Name = "🌓 Automată")]
Auto = 3
}
private Theme userTheme = Theme.Auto;
}
3. Atribute disponibile
Proprietate |
Tip |
Descriere |
Valoare Implicită |
Value |
T |
Valoarea selectată |
default(T) |
Type |
FodRadioType |
Stilul vizual (Radio sau Button) |
Radio |
Disable |
bool |
Dezactivează toate opțiunile |
false |
BoldText |
bool |
Text îngroșat pentru etichete |
false |
LabelFontSize |
int |
Dimensiune font etichete (px) |
null |
InputFontSize |
int |
Dimensiune font input-uri (px) |
null |
Options |
IEnumerable<SelectableItem<T>> |
Opțiuni disponibile |
null |
ItemLabels |
IEnumerable<KeyValuePair<T, string>> |
Etichete personalizate |
null |
Source |
IEnumerable<T> |
Sursă de date |
null |
Label |
string |
Eticheta grupului |
null |
Required |
bool |
Câmp obligatoriu |
false |
OnValueChanged |
EventCallback<T> |
Callback la schimbare |
- |
Proprietate |
Tip |
Descriere |
Valoare Implicită |
Item |
SelectableItem<T> |
Elementul de date |
- |
Disable |
bool |
Dezactivează radio-ul |
false |
LabelFontSize |
int |
Dimensiune font etichetă |
null |
InputFontSize |
int |
Dimensiune font input |
null |
Label |
string |
Etichetă personalizată |
null |
4. Tipuri și Enumerări
FodRadioType
public enum FodRadioType
{
Radio = 1, // Butoane radio tradiționale
Button = 2 // Grup de butoane stil modern
}
OnBehalfOnEnum
public enum OnBehalfOnEnum
{
Personal = 1, // În nume propriu
MPowerAuthorization = 2,// Cu împuternicire MPower
Custom = 3 // Personalizat
}
5. Evenimente
Eveniment |
Tip |
Descriere |
ValueChanged |
EventCallback<T> |
Se declanșează la schimbarea selecției |
OnValueChanged |
EventCallback<T> |
Alias pentru ValueChanged |
6. Componente asociate
- FODSelectableFormComponent - Clasa de bază pentru componente de selecție
- SelectableItem - Model pentru elemente selectabile
- Tooltip - Pentru afișarea descrierilor
- ValidationMessage - Pentru afișarea erorilor de validare
7. Stilizare și personalizare
/* Personalizare grup butoane */
.fod-radio-button-group {
border-radius: 0.625rem;
overflow: hidden;
}
.fod-radio-button-group .btn {
border-radius: 0;
border: 1px solid var(--fod-primary);
}
.fod-radio-button-group .btn.active {
background-color: var(--fod-primary);
color: white;
}
/* Animații pentru tranziții */
.fod-radio-button-group .btn {
transition: all 0.3s ease;
}
.fod-radio-button-group .btn:hover:not(.active) {
background-color: rgba(var(--fod-primary-rgb), 0.1);
}
Stilizare radio tradițional
/* Radio buttons personalizate */
.form-check-input[type="radio"] {
width: 1.25rem;
height: 1.25rem;
border: 2px solid #dee2e6;
transition: all 0.2s ease;
}
.form-check-input[type="radio"]:checked {
background-color: var(--fod-primary);
border-color: var(--fod-primary);
}
/* Label styling */
.form-check-label {
padding-left: 0.5rem;
cursor: pointer;
}
8. Localizare automată pentru enum-uri
public enum DocumentType
{
[Display(Name = "Pașaport",
Description = "Document de călătorie internațional",
ResourceType = typeof(Resources))]
Passport = 1,
[Display(Name = "Buletin de identitate",
Description = "Act de identitate național")]
IdentityCard = 2
}
9. Integrare cu validare
<EditForm Model="model" OnValidSubmit="HandleSubmit">
<DataAnnotationsValidator />
<FODInputRadioGroup T="AcceptanceStatus"
@bind-Value="model.Status"
Label="Acceptați termenii?"
For="@(() => model.Status)" />
<ValidationMessage For="@(() => model.Status)" />
</EditForm>
@code {
public class Model
{
[Required(ErrorMessage = "Trebuie să selectați o opțiune")]
[Range(1, 1, ErrorMessage = "Trebuie să acceptați termenii")]
public AcceptanceStatus Status { get; set; }
}
public enum AcceptanceStatus
{
[Display(Name = "Accept")]
Accept = 1,
[Display(Name = "Refuz")]
Refuse = 2
}
}
10. Note și observații
- Pentru enum-uri, localizarea se face automat prin atributul Display
- Stilul Button este recomandat pentru 2-4 opțiuni
- Pentru liste lungi (>5 opțiuni), considerați FodSelect
- Validarea funcționează identic cu alte componente de formular
- Tooltips-urile apar la hover pentru descrieri lungi
11. Diferențe între stiluri
Caracteristică |
Radio |
Button |
Aspect |
Cerc cu punct |
Butoane grupate |
Spațiu ocupat |
Vertical extins |
Compact orizontal |
Cazuri de utilizare |
Formulare tradiționale |
UI modern |
Număr optim opțiuni |
2-10 |
2-4 |
12. Bune practici
- Etichete clare - Folosiți nume descriptive pentru opțiuni
- Ordine logică - Aranjați opțiunile în ordine naturală
- Valoare implicită - Setați o valoare implicită sensibilă
- Validare - Adăugați validare pentru câmpuri obligatorii
- Descrieri - Folosiți tooltips pentru clarificări
- Stil consistent - Păstrați același stil în formular
13. Troubleshooting
Radio-urile nu se actualizează
- Verificați că folosiți
@bind-Value
corect
- Asigurați-vă că tipul T este consistent
Etichetele nu apar
- Verificați atributul Display pe enum
- Pentru date custom, verificați proprietățile Text/Name
Validarea nu funcționează
- Adăugați
DataAnnotationsValidator
în EditForm
- Folosiți
ValidationMessage
pentru afișare erori
14. Concluzie
Sistemul de componente radio oferă o soluție completă și flexibilă pentru selecții unice în formulare, cu suport excelent pentru localizare, validare și personalizare vizuală.