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.
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
Model
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]
public 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]
public 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 EditContextModelke .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.
Secara default, 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 proyek utama Aplikasi Web.
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]
public 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]
public 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.
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")]
public Holodeck? Model1 { get; set; }
[SupplyParameterFromForm(FormName = "Holodeck2")]
public 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; }
}
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();
}
}
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>
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]
public 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);
}
}
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.
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
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk