pengikatan formulir inti Blazor ASP.NET
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Artikel ini menjelaskan cara menggunakan pengikatan dalam Blazor formulir.
EditForm
/EditContext
pola
Membuat EditForm berdasarkan objek yang EditContext ditetapkan sebagai nilai berskala untuk komponen lain dalam formulir. Metadata EditContext trek tentang proses edit, termasuk bidang formulir mana yang telah dimodifikasi dan pesan validasi saat ini. Menetapkan ke EditForm.Model atau dapat EditForm.EditContext mengikat formulir ke data.
Pengikatan model
Penugasan ke EditForm.Model:
<EditForm ... Model="Model" ...>
...
</EditForm>
@code {
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
}
<EditForm ... Model="Model" ...>
...
</EditForm>
@code {
public Starship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
}
Catatan
Sebagian besar contoh model formulir artikel ini mengikat formulir ke properti C#, tetapi pengikatan bidang C# juga didukung.
Pengikatan konteks
Penugasan ke EditForm.EditContext:
<EditForm ... EditContext="editContext" ...>
...
</EditForm>
@code {
private EditContext? editContext;
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
}
}
<EditForm ... EditContext="editContext" ...>
...
</EditForm>
@code {
private EditContext? editContext;
public Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
}
}
Tetapkan atau EditContext Model ke .EditForm Jika keduanya ditetapkan, kesalahan runtime dilemparkan.
Jenis yang didukung
Pengikatan mendukung:
- Jenis primitif
- Koleksi
- Jenis kompleks
- Jenis rekursif
- Jenis dengan konstruktor
- Enums
Anda juga dapat menggunakan [DataMember]
atribut dan [IgnoreDataMember]
untuk menyesuaikan pengikatan model. Gunakan atribut ini untuk mengganti nama properti, mengabaikan properti, dan menandai properti sesuai kebutuhan.
Opsi pengikatan tambahan
Opsi pengikatan model tambahan tersedia saat RazorComponentsServiceOptions memanggil AddRazorComponents:
- MaxFormMappingCollectionSize: Jumlah maksimum elemen yang diizinkan dalam koleksi formulir.
- MaxFormMappingRecursionDepth: Kedalaman maksimum yang diizinkan saat memetakan data formulir secara rekursif.
- MaxFormMappingErrorCount: Jumlah maksimum kesalahan yang diizinkan saat memetakan data formulir.
- MaxFormMappingKeySize: Ukuran maksimum buffer yang digunakan untuk membaca kunci data formulir.
Berikut ini menunjukkan nilai default yang ditetapkan oleh kerangka kerja:
builder.Services.AddRazorComponents(options =>
{
options.FormMappingUseCurrentCulture = true;
options.MaxFormMappingCollectionSize = 1024;
options.MaxFormMappingErrorCount = 200;
options.MaxFormMappingKeySize = 1024 * 2;
options.MaxFormMappingRecursionDepth = 64;
}).AddInteractiveServerComponents();
Nama formulir
FormName Gunakan parameter untuk menetapkan nama formulir. Nama formulir harus unik untuk mengikat data model. Formulir berikut diberi nama RomulanAle
:
<EditForm ... FormName="RomulanAle" ...>
...
</EditForm>
Menyediakan nama formulir:
- Diperlukan untuk semua formulir yang dikirimkan oleh komponen sisi server yang dirender secara statis.
- Tidak diperlukan untuk formulir yang dikirimkan oleh komponen yang dirender secara interaktif, yang mencakup formulir dalam Blazor WebAssembly aplikasi dan komponen dengan mode render interaktif. Namun, sebaiknya berikan nama formulir unik untuk setiap formulir untuk mencegah kesalahan posting formulir runtime jika interaktivitas pernah dihilangkan untuk formulir.
Nama formulir hanya diperiksa ketika formulir diposting ke titik akhir sebagai permintaan HTTP POST tradisional dari komponen sisi server yang dirender secara statis. Kerangka kerja tidak melemparkan pengecualian pada titik penyajian formulir, tetapi hanya pada saat HTTP POST tiba dan tidak menentukan nama formulir.
Ada cakupan formulir yang tidak disebutkan namanya (string kosong) di atas komponen akar aplikasi, yang cukup ketika tidak ada tabrakan nama formulir di aplikasi. Jika tabrakan nama formulir dimungkinkan, seperti saat menyertakan formulir dari pustaka dan Anda tidak memiliki kontrol atas nama formulir yang digunakan oleh pengembang pustaka, berikan cakupan nama formulir dengan FormMappingScope komponen dalam Blazor Web Appproyek utama.
Dalam contoh berikut, HelloFormFromLibrary
komponen memiliki formulir bernama Hello
dan berada di pustaka.
HelloFormFromLibrary.razor
:
<EditForm FormName="Hello" Model="this" OnSubmit="Submit">
<InputText @bind-Value="Name" />
<button type="submit">Submit</button>
</EditForm>
@if (submitted)
{
<p>Hello @Name from the library's form!</p>
}
@code {
bool submitted = false;
[SupplyParameterFromForm]
private string? Name { get; set; }
private void Submit() => submitted = true;
}
Komponen berikut NamedFormsWithScope
menggunakan komponen pustaka HelloFormFromLibrary
dan juga memiliki formulir bernama Hello
. Nama FormMappingScope cakupan komponen adalah ParentContext
untuk formulir apa pun yang disediakan oleh HelloFormFromLibrary
komponen. Meskipun kedua formulir dalam contoh ini memiliki nama formulir (Hello
), nama formulir tidak bertabrakan dan peristiwa dirutekan ke formulir yang benar untuk peristiwa POST formulir.
NamedFormsWithScope.razor
:
@page "/named-forms-with-scope"
<div>Hello form from a library</div>
<FormMappingScope Name="ParentContext">
<HelloFormFromLibrary />
</FormMappingScope>
<div>Hello form using the same form name</div>
<EditForm FormName="Hello" Model="this" OnSubmit="Submit">
<InputText @bind-Value="Name" />
<button type="submit">Submit</button>
</EditForm>
@if (submitted)
{
<p>Hello @Name from the app form!</p>
}
@code {
bool submitted = false;
[SupplyParameterFromForm]
private string? Name { get; set; }
private void Submit() => submitted = true;
}
Menyediakan parameter dari formulir ([SupplyParameterFromForm]
)
Atribut [SupplyParameterFromForm]
menunjukkan bahwa nilai properti terkait harus disediakan dari data formulir untuk formulir. Data dalam permintaan yang cocok dengan nama properti terikat ke properti . Input berdasarkan InputBase<TValue>
hasilkan nama nilai formulir yang cocok dengan nama Blazor yang digunakan untuk pengikatan model. Tidak seperti properti parameter komponen ([Parameter]
), properti yang dianotasi dengan [SupplyParameterFromForm]
tidak perlu ditandai public
.
Anda dapat menentukan parameter pengikatan formulir berikut ke [SupplyParameterFromForm]
atribut :
- Name: Mendapatkan atau mengatur nama untuk parameter . Nama ini digunakan untuk menentukan awalan yang akan digunakan untuk mencocokkan data formulir dan memutuskan apakah nilai perlu diikat atau tidak.
- FormName: Mendapatkan atau mengatur nama untuk handler. Nama digunakan untuk mencocokkan parameter dengan formulir menurut nama formulir untuk memutuskan apakah nilai perlu diikat atau tidak.
Contoh berikut secara independen mengikat dua formulir ke modelnya berdasarkan nama formulir.
Starship6.razor
:
@page "/starship-6"
@inject ILogger<Starship6> Logger
<EditForm Model="Model1" OnSubmit="Submit1" FormName="Holodeck1">
<div>
<label>
Holodeck 1 Identifier:
<InputText @bind-Value="Model1!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
<EditForm Model="Model2" OnSubmit="Submit2" FormName="Holodeck2">
<div>
<label>
Holodeck 2 Identifier:
<InputText @bind-Value="Model2!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm(FormName = "Holodeck1")]
private Holodeck? Model1 { get; set; }
[SupplyParameterFromForm(FormName = "Holodeck2")]
private Holodeck? Model2 { get; set; }
protected override void OnInitialized()
{
Model1 ??= new();
Model2 ??= new();
}
private void Submit1() => Logger.LogInformation("Submit1: Id={Id}", Model1?.Id);
private void Submit2() => Logger.LogInformation("Submit2: Id={Id}", Model2?.Id);
public class Holodeck
{
public string? Id { get; set; }
}
}
@page "/starship-6"
@inject ILogger<Starship6> Logger
<EditForm Model="Model1" OnSubmit="Submit1" FormName="Holodeck1">
<div>
<label>
Holodeck 1 Identifier:
<InputText @bind-Value="Model1!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
<EditForm Model="Model2" OnSubmit="Submit2" FormName="Holodeck2">
<div>
<label>
Holodeck 2 Identifier:
<InputText @bind-Value="Model2!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm(FormName = "Holodeck1")]
private Holodeck? Model1 { get; set; }
[SupplyParameterFromForm(FormName = "Holodeck2")]
private Holodeck? Model2 { get; set; }
protected override void OnInitialized()
{
Model1 ??= new();
Model2 ??= new();
}
private void Submit1() => Logger.LogInformation("Submit1: Id={Id}", Model1?.Id);
private void Submit2() => Logger.LogInformation("Submit2: Id={Id}", Model2?.Id);
public class Holodeck
{
public string? Id { get; set; }
}
}
Formulir berlapis dan mengikat
Panduan berikut menunjukkan cara bersarang dan mengikat formulir anak.
Kelas detail pengiriman berikut (ShipDetails
) menyimpan deskripsi dan panjang untuk subformulir.
ShipDetails.cs
:
namespace BlazorSample;
public class ShipDetails
{
public string? Description { get; set; }
public int? Length { get; set; }
}
namespace BlazorSample;
public class ShipDetails
{
public string? Description { get; set; }
public int? Length { get; set; }
}
Kelas berikut menamai Ship
pengidentifikasi (Id
) dan menyertakan detail pengiriman.
Ship.cs
:
namespace BlazorSample
{
public class Ship
{
public string? Id { get; set; }
public ShipDetails Details { get; set; } = new();
}
}
namespace BlazorSample
{
public class Ship
{
public string? Id { get; set; }
public ShipDetails Details { get; set; } = new();
}
}
Subformulir berikut digunakan untuk mengedit nilai jenis ShipDetails
. Ini diimplementasikan dengan mewarisi Editor<T> di bagian atas komponen. Editor<T> memastikan bahwa komponen anak menghasilkan nama bidang formulir yang benar berdasarkan model (T
), di mana T
dalam contoh berikut adalah ShipDetails
.
StarshipSubform.razor
:
@inherits Editor<ShipDetails>
<div>
<label>
Description:
<InputText @bind-Value="Value!.Description" />
</label>
</div>
<div>
<label>
Length:
<InputNumber @bind-Value="Value!.Length" />
</label>
</div>
@inherits Editor<ShipDetails>
<div>
<label>
Description:
<InputText @bind-Value="Value!.Description" />
</label>
</div>
<div>
<label>
Length:
<InputNumber @bind-Value="Value!.Length" />
</label>
</div>
Bentuk utama terikat ke Ship
kelas . Komponen StarshipSubform
ini digunakan untuk mengedit detail pengiriman, terikat sebagai Model!.Details
.
Starship7.razor
:
@page "/starship-7"
@inject ILogger<Starship7> Logger
<EditForm Model="Model" OnSubmit="Submit" FormName="Starship7">
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<StarshipSubform @bind-Value="Model!.Details" />
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm]
private Ship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private void Submit() =>
Logger.LogInformation("Id = {Id} Desc = {Description} Length = {Length}",
Model?.Id, Model?.Details?.Description, Model?.Details?.Length);
}
@page "/starship-7"
@inject ILogger<Starship7> Logger
<EditForm Model="Model" OnSubmit="Submit" FormName="Starship7">
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<StarshipSubform @bind-Value="Model!.Details" />
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm]
private Ship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private void Submit() =>
Logger.LogInformation("Id = {Id} Desc = {Description} Length = {Length}",
Model?.Id, Model?.Details?.Description, Model?.Details?.Length);
}
Menginisialisasi data formulir dengan SSR statis
Ketika komponen mengadopsi SSR statis, OnInitialized{Async}
metode siklus hidup dan OnParametersSet{Async}
metode siklus hidup diaktifkan ketika komponen awalnya dirender dan pada setiap formulir POST ke server. Untuk menginisialisasi nilai model formulir, konfirmasikan apakah model sudah memiliki data sebelum menetapkan nilai model baru di , seperti yang ditunjukkan OnParametersSet{Async}
contoh berikut.
StarshipInit.razor
:
@page "/starship-init"
@inject ILogger<StarshipInit> Logger
<EditForm Model="Model" OnValidSubmit="Submit" FormName="StarshipInit">
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
protected override void OnParametersSet()
{
if (Model!.Id == default)
{
LoadData();
}
}
private void LoadData()
{
Model!.Id = "Set by LoadData";
}
private void Submit()
{
Logger.LogInformation("Id = {Id}", Model?.Id);
}
public class Starship
{
public string? Id { get; set; }
}
}
Skenario kesalahan pemetaan formulir tingkat lanjut
Kerangka kerja membuat instans dan mengisi FormMappingContext formulir, yang merupakan konteks yang terkait dengan operasi pemetaan formulir tertentu. Setiap cakupan pemetaan (ditentukan oleh FormMappingScope komponen) membuat instans FormMappingContext. Setiap kali meminta konteks untuk nilai, kerangka kerja mengisi FormMappingContext dengan nilai yang [SupplyParameterFromForm]
dicoba dan kesalahan pemetaan apa pun.
Pengembang tidak diharapkan untuk berinteraksi secara FormMappingContext langsung, karena ini terutama sumber data untuk InputBase<TValue>, EditContext, dan implementasi internal lainnya untuk menunjukkan kesalahan pemetaan sebagai kesalahan validasi. Dalam skenario kustom tingkat lanjut, pengembang dapat mengakses FormMappingContext langsung sebagai [CascadingParameter]
untuk menulis kode kustom yang menggunakan nilai yang dicoba dan kesalahan pemetaan.
Komponen input kustom
Untuk skenario pemrosesan input kustom, sub bagian berikut menunjukkan komponen input kustom:
Komponen input berdasarkan
InputBase<T>
: Komponen mewarisi dari InputBase<TValue>, yang menyediakan implementasi dasar untuk pengikatan, panggilan balik, dan validasi. Komponen yang mewarisi harus InputBase<TValue> digunakan dalam Blazor bentuk (EditForm).Komponen input dengan kontrol pengembang penuh: Komponen mengambil kontrol penuh atas pemrosesan input. Kode komponen harus mengelola pengikatan, panggilan balik, dan validasi. Komponen dapat digunakan di dalam atau di luar Blazor formulir.
Kami menyarankan agar Anda memperoleh komponen InputBase<TValue> input kustom kecuali persyaratan tertentu mencegah Anda melakukannya. Kelas InputBase<TValue> ini secara aktif dikelola oleh tim ASP.NET Core, memastikannya tetap terbarui dengan fitur dan perubahan kerangka kerja terbaru Blazor .
Komponen input berdasarkan InputBase<T>
Contoh komponen berikut:
- Mewarisi dari InputBase<TValue>. Komponen yang mewarisi harus InputBase<TValue> digunakan dalam Blazor bentuk (EditForm).
- Mengambil input boolean dari kotak centang.
- Mengatur warna latar belakang kontainernya
<div>
berdasarkan status kotak centang, yang terjadi ketikaAfterChange
metode dijalankan setelah pengikatan (@bind:after
). - Diperlukan untuk mengambil alih metode kelas
TryParseValueFromString
dasar tetapi tidak memproses data input string karena kotak centang tidak menyediakan data string. Contoh implementasiTryParseValueFromString
untuk jenis komponen input lain yang memproses input string tersedia di sumber referensi ASP.NET Core.
Catatan
Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).
EngineeringApprovalInputDerived.razor
:
@using System.Diagnostics.CodeAnalysis
@inherits InputBase<bool>
<div class="@divCssClass">
<label>
Engineering Approval:
<input @bind="CurrentValue" @bind:after="AfterChange" class="@CssClass"
type="checkbox" />
</label>
</div>
@code {
private string? divCssClass;
private void AfterChange()
{
divCssClass = CurrentValue ? "bg-success text-white" : null;
}
protected override bool TryParseValueFromString(
string? value, out bool result,
[NotNullWhen(false)] out string? validationErrorMessage)
=> throw new NotSupportedException(
"This component does not parse string inputs. " +
$"Bind to the '{nameof(CurrentValue)}' property, " +
$"not '{nameof(CurrentValueAsString)}'.");
}
Untuk menggunakan komponen sebelumnya dalam formulir contoh starship (Starship.cs
/Starship3.razor
), ganti <div>
blok untuk bidang persetujuan teknik dengan instans komponen yang EngineeringApprovalInputDerived
terikat ke properti model:IsValidatedDesign
- <div>
- <label>
- Engineering Approval:
- <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
- </label>
- </div>
+ <EngineeringApprovalInputDerived @bind-Value="Model!.IsValidatedDesign" />
Komponen input dengan kontrol pengembang penuh
Contoh komponen berikut:
- Tidak mewarisi dari InputBase<TValue>. Komponen mengambil kontrol penuh pemrosesan input, termasuk pengikatan, panggilan balik, dan validasi. Komponen dapat digunakan di dalam atau di luar Blazor formulir (EditForm).
- Mengambil input boolean dari kotak centang.
- Ubah warna latar belakang jika kotak centang dicentang.
Kode dalam komponen meliputi:
Properti
Value
digunakan dengan pengikatan dua arah untuk mendapatkan atau mengatur nilai input.ValueChanged
adalah panggilan balik yang memperbarui nilai terikat.Saat digunakan dalam Blazor formulir:
- EditContext adalah nilai berskala.
fieldCssClass
menata bidang berdasarkan hasil EditContext validasi.ValueExpression
adalah ekspresi (Expression<Func<T>>
) yang ditetapkan oleh kerangka kerja yang mengidentifikasi nilai terikat.- FieldIdentifier secara unik mengidentifikasi satu bidang yang dapat diedit, biasanya sesuai dengan properti model. Pengidentifikasi bidang dibuat dengan ekspresi yang mengidentifikasi nilai terikat (
ValueExpression
).
Di penanganan
OnChange
aktivitas:- Nilai input kotak centang diperoleh dari InputFileChangeEventArgs.
- Warna latar belakang dan warna teks elemen kontainer
<div>
diatur. - EventCallback.InvokeAsync memanggil delegasi yang terkait dengan pengikatan dan mengirimkan pemberitahuan peristiwa kepada konsumen bahwa nilai telah berubah.
- Jika komponen digunakan dalam EditForm (
EditContext
properti tidaknull
), EditContext.NotifyFieldChanged dipanggil untuk memicu validasi.
EngineeringApprovalInputStandalone.razor
:
@using System.Globalization
@using System.Linq.Expressions
<div class="@divCssClass">
<label>
Engineering Approval:
<input class="@fieldCssClass" @onchange="OnChange" type="checkbox"
value="@Value" />
</label>
</div>
@code {
private string? divCssClass;
private FieldIdentifier fieldIdentifier;
private string? fieldCssClass => EditContext?.FieldCssClass(fieldIdentifier);
[CascadingParameter]
private EditContext? EditContext { get; set; }
[Parameter]
public bool? Value { get; set; }
[Parameter]
public EventCallback<bool> ValueChanged { get; set; }
[Parameter]
public Expression<Func<bool>>? ValueExpression { get; set; }
protected override void OnInitialized()
{
fieldIdentifier = FieldIdentifier.Create(ValueExpression!);
}
private async Task OnChange(ChangeEventArgs args)
{
BindConverter.TryConvertToBool(args.Value, CultureInfo.CurrentCulture,
out var value);
divCssClass = value ? "bg-success text-white" : null;
await ValueChanged.InvokeAsync(value);
EditContext?.NotifyFieldChanged(fieldIdentifier);
}
}
Untuk menggunakan komponen sebelumnya dalam formulir contoh starship (Starship.cs
/Starship3.razor
), ganti <div>
blok untuk bidang persetujuan teknik dengan instans komponen yang EngineeringApprovalInputStandalone
terikat ke properti model:IsValidatedDesign
- <div>
- <label>
- Engineering Approval:
- <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
- </label>
- </div>
+ <EngineeringApprovalInputStandalone @bind-Value="Model!.IsValidatedDesign" />
Komponen EngineeringApprovalInputStandalone
ini juga berfungsi di luar EditForm:
<EngineeringApprovalInputStandalone @bind-Value="ValidDesign" />
<div>
<b>ValidDesign:</b> @ValidDesign
</div>
@code {
private bool ValidDesign { get; set; }
}
Tombol radio
Contoh di bagian ini didasarkan pada Starfleet Starship Database
formulir (Starship3
komponen) dari bagian Formulir contoh dari artikel ini.
Tambahkan jenis berikut enum
ke aplikasi. Buat file baru untuk menahannya atau menambahkannya ke Starship.cs
file.
public class ComponentEnums
{
public enum Manufacturer { SpaceX, NASA, ULA, VirginGalactic, Unknown }
public enum Color { ImperialRed, SpacecruiserGreen, StarshipBlue, VoyagerOrange }
public enum Engine { Ion, Plasma, Fusion, Warp }
}
ComponentEnums
Buat kelas dapat diakses oleh:
Starship
model diStarship.cs
(misalnya,using static ComponentEnums;
).Starfleet Starship Database
form (Starship3.razor
) (misalnya,@using static ComponentEnums
).
Gunakan InputRadio<TValue> komponen dengan InputRadioGroup<TValue> komponen untuk membuat grup tombol radio. Dalam contoh berikut, properti ditambahkan ke Starship
model yang dijelaskan di bagian Formulir contoh dari artikel Komponen input:
[Required]
[Range(typeof(Manufacturer), nameof(Manufacturer.SpaceX),
nameof(Manufacturer.VirginGalactic), ErrorMessage = "Pick a manufacturer.")]
public Manufacturer Manufacturer { get; set; } = Manufacturer.Unknown;
[Required, EnumDataType(typeof(Color))]
public Color? Color { get; set; } = null;
[Required, EnumDataType(typeof(Engine))]
public Engine? Engine { get; set; } = null;
Starfleet Starship Database
Perbarui formulir (Starship3
komponen) dari bagian Formulir contoh dari artikel Komponen input. Tambahkan komponen yang akan dihasilkan:
- Grup tombol radio untuk produsen kapal.
- Grup tombol radio berlapis untuk mesin dan warna pengiriman.
Catatan
Grup tombol radio berlapis tidak sering digunakan dalam formulir karena dapat mengakibatkan tata letak kontrol formulir yang tidak terorganisir yang dapat membingungkan pengguna. Namun, ada kasus ketika mereka masuk akal dalam desain UI, seperti dalam contoh berikut yang memasangkan rekomendasi untuk dua input pengguna, mesin pengiriman dan warna kapal. Satu mesin dan satu warna diperlukan oleh validasi formulir. Tata letak formulir menggunakan sarang berlapis untuk memasangkan InputRadioGroup<TValue>mesin dan rekomendasi warna. Namun, pengguna dapat menggabungkan mesin apa pun dengan warna apa pun untuk mengirimkan formulir.
Catatan
Pastikan untuk membuat ComponentEnums
kelas tersedia untuk komponen untuk contoh berikut:
@using static ComponentEnums
<fieldset>
<legend>Manufacturer</legend>
<InputRadioGroup @bind-Value="Model!.Manufacturer">
@foreach (var manufacturer in Enum.GetValues<Manufacturer>())
{
<div>
<label>
<InputRadio Value="manufacturer" />
@manufacturer
</label>
</div>
}
</InputRadioGroup>
</fieldset>
<fieldset>
<legend>Engine and Color</legend>
<p>
Engine and color pairs are recommended, but any
combination of engine and color is allowed.
</p>
<InputRadioGroup Name="engine" @bind-Value="Model!.Engine">
<InputRadioGroup Name="color" @bind-Value="Model!.Color">
<div style="margin-bottom:5px">
<div>
<label>
<InputRadio Name="engine" Value="Engine.Ion" />
Ion
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="Color.ImperialRed" />
Imperial Red
</label>
</div>
</div>
<div style="margin-bottom:5px">
<div>
<label>
<InputRadio Name="engine" Value="Engine.Plasma" />
Plasma
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="Color.SpacecruiserGreen" />
Spacecruiser Green
</label>
</div>
</div>
<div style="margin-bottom:5px">
<div>
<label>
<InputRadio Name="engine" Value="Engine.Fusion" />
Fusion
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="Color.StarshipBlue" />
Starship Blue
</label>
</div>
</div>
<div style="margin-bottom:5px">
<div>
<label>
<InputRadio Name="engine" Value="Engine.Warp" />
Warp
</label>
</div>
<div>
<label>
<InputRadio Name="color" Value="Color.VoyagerOrange" />
Voyager Orange
</label>
</div>
</div>
</InputRadioGroup>
</InputRadioGroup>
</fieldset>
Catatan
Jika Name
dihilangkan, InputRadio<TValue> komponen dikelompokkan oleh leluhur terbarunya.
Jika Anda menerapkan markup sebelumnya Razor di Starship3
komponen bagian Formulir contoh dari artikel Komponen input, perbarui pengelogan untuk Submit
metode :
Logger.LogInformation("Id = {Id} Description = {Description} " +
"Classification = {Classification} MaximumAccommodation = " +
"{MaximumAccommodation} IsValidatedDesign = " +
"{IsValidatedDesign} ProductionDate = {ProductionDate} " +
"Manufacturer = {Manufacturer}, Engine = {Engine}, " +
"Color = {Color}",
Model?.Id, Model?.Description, Model?.Classification,
Model?.MaximumAccommodation, Model?.IsValidatedDesign,
Model?.ProductionDate, Model?.Manufacturer, Model?.Engine,
Model?.Color);
Saat bekerja dengan tombol radio dalam bentuk, pengikatan data ditangani secara berbeda dari elemen lain karena tombol radio dievaluasi sebagai grup. Nilai setiap tombol radio diperbaiki, tetapi nilai grup tombol radio adalah nilai tombol radio yang dipilih. Contoh berikut menunjukkan cara membatalkan pekerjaan.
- Menangani pengikatan data untuk grup tombol radio.
- Mendukung validasi menggunakan komponen kustom InputRadio<TValue> .
InputRadio.razor
:
@using System.Globalization
@inherits InputBase<TValue>
@typeparam TValue
<input @attributes="AdditionalAttributes" type="radio" value="@SelectedValue"
checked="@(SelectedValue.Equals(Value))" @onchange="OnChange" />
@code {
[Parameter]
public TValue SelectedValue { get; set; }
private void OnChange(ChangeEventArgs args)
{
CurrentValueAsString = args.Value.ToString();
}
protected override bool TryParseValueFromString(string value,
out TValue result, out string errorMessage)
{
var success = BindConverter.TryConvertTo<TValue>(
value, CultureInfo.CurrentCulture, out var parsedValue);
if (success)
{
result = parsedValue;
errorMessage = null;
return true;
}
else
{
result = default;
errorMessage = "The field isn't valid.";
return false;
}
}
}
Untuk informasi selengkapnya tentang parameter jenis generik (@typeparam
), lihat artikel berikut ini:
- Referensi sintaks Razor untuk ASP.NET Core
- komponen ASP.NET Core Razor
- Komponen template Blazor ASP.NET Core
Gunakan contoh model berikut.
StarshipModel.cs
:
using System.ComponentModel.DataAnnotations;
namespace BlazorServer80
{
public class Model
{
[Range(1, 5)]
public int Rating { get; set; }
}
}
Komponen berikut RadioButtonExample
menggunakan komponen sebelumnya InputRadio
untuk mendapatkan dan memvalidasi peringkat dari pengguna:
RadioButtonExample.razor
:
@page "/radio-button-example"
@using System.ComponentModel.DataAnnotations
@using Microsoft.Extensions.Logging
@inject ILogger<RadioButtonExample> Logger
<h1>Radio Button Example</h1>
<EditForm Model="Model" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
@for (int i = 1; i <= 5; i++)
{
<div>
<label>
<InputRadio name="rate" SelectedValue="i"
@bind-Value="Model.Rating" />
@i
</label>
</div>
}
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
<div>@Model.Rating</div>
@code {
public StarshipModel Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private void HandleValidSubmit()
{
Logger.LogInformation("HandleValidSubmit called");
}
}
ASP.NET Core