首页 Blazor 模型绑定与校验
文章
取消

Blazor 模型绑定与校验

Blazor 框架支持 WebForm 并使用 EditForm 绑定到组件上进行模型验证。验证的过程则是:EditForm 基于分配的模型实例创建了EditContext,用作窗体中其他组件的EditForm。EditContext 跟踪有关编辑进程的元数据,其中包括已修改的字段和当前的验证消息;通过提供OnValidSubmit事件让其在提交含有效字段的窗体时运行处理窗体提交,OnInvalidSubmit 事件让其在提交含无效字段的窗体时运行,使用OnSubmit事件让其在不考虑窗体字段验证状态的情况下运行,通过调用事件处理程序方法中的 EditContext.Validate 来验证窗体如果 Validate返回true则窗体有效。

EditForm模型绑定验证

定义待验证的模型Starship 包含了数据注释的多个属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.ComponentModel.DataAnnotations;
public class Starship
{
    [Required]
    [StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")]
    public string? Identifier { get; set; }
    public string? Description { get; set; }

    [Required]
    public string? Classification { get; set; }
    [Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")]
    public int MaximumAccommodation { get; set; }

    [Required]
    [Range(typeof(bool), "true", "true",
			ErrorMessage = "This form disallows unapproved ships.")]
    public bool IsValidatedDesign { get; set; }

    [Required]
    public DateTime ProductionDate { get; set; }
}

通过以下内容接受和验证用户输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<EditForm Model="@starship" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator></DataAnnotationsValidator>
<ValidationSummary></ValidationSummary>
<p>
<label>
Identifier: <InputText @bind-Value="starship.Identifier"></InputText>
</label>
</p>
<p>
<label>
Description (optional): <InputTextArea @bind-Value="starship.Description"></InputTextArea>
</label>
</p>
<p>
<label>
Primary Classification: <InputSelect @bind-Value="starship.Classification">
<option value="">Select classification ...</option>
<option value="Exploration">Exploration</option>
<option value="Diplomacy">Diplomacy</option>
<option value="Defense">Defense</option>
</InputSelect>
</label>
</p>
<p>
<label>
Maximum Accommodation:<InputNumber @bind-Value="starship.MaximumAccommodation"></InputNumber>
</label>
</p>
<p>
<label>
Engineering Approval:<InputCheckbox @bind-Value="starship.IsValidatedDesign"></InputCheckbox>
</label>
</p>
<p>
<label>
Production Date:<InputDate @bind-Value="starship.ProductionDate"></InputDate>
</label>
</p>
<button type="submit">Submit</button>
</EditForm>
@code {
private Starship starship = new() { ProductionDate = DateTime.UtcNow };
private void HandleValidSubmit()
{
Logger.LogInformation("HandleValidSubmit called");
// Process the valid form
}

其中DataAnnotationsValidator 组件将数据注释验证附加到级联 EditContext。 启用数据注释验证需要DataAnnotationsValidator组件。 若要使用不同于数据注释的验证系统,请用自定义实现替换 DataAnnotationsValidator组件 ValidationSummary 组件用于汇总所有验证消息, EditForm 基于分配的 Starship 实例创建 EditContext (Model=”@starship”) 并处理有效的窗体 editorfrom

EditForm基本验证

在基本窗体验证场景中,EditForm 实例可以使用声明的 EditContext 和 ValidationMessageStore 来校验,EditContext组件的OnValidationRequested 事件处理程序执行自定义验证逻辑,处理程序的结果会更新 ValidationMessageStore 实例 在组件中增加代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<EditForm EditContext="editContext" OnValidSubmit="@HandleValidSubmit">
<label>
	Type 1:
	<InputCheckbox @bind-Value="holodeck.Type1" />
</label>
<label>
	Type 2:
	<InputCheckbox @bind-Value="holodeck.Type2" />
</label>
<button type="submit">Update</button>
<ValidationMessage For="() => holodeck.Options" />
</EditForm>
@code{
public class Holodeck
{
public bool Type1 { get; set; }
public bool Type2 { get; set; }
public bool Options => Type1 || Type2;
}

private EditContext? editContext;
private Holodeck holodeck = new();
private ValidationMessageStore? messageStore;
protected override void OnInitialized()
{
		editContext=new EditContext(holodeck);
		editContext.OnValidationRequested+=HandleValidationRequested;
		messageStore=new(editContext);
}
private void HandleValidationRequested(object? sender,ValidationRequestedEventArgs args)
{
	messageStore?.Clear();
	// Custom validation logic
	if (!holodeck.Options)
	{
			messageStore?.Add(() => holodeck.Options, "Select at least one.");
	}
}
private void HandleValidSubmit()
{
	Logger.LogInformation("HandleValidSubmit called: Processing the form");
	// Process the form
}
public void Dispose()
{
if (editContext is not null)
{
	editContext.OnValidationRequested -= HandleValidationRequested;
}
}
}

HandleValidationRequested 处理程序方法通过在验证窗体之前调用 ValidationMessageStore.Clear 来清除任何现有的验证消息

自定义验证 CSS 类属性

在校验失败时使用自定义的css来提示用户,在wwwroot/css/app.css (Blazor WebAssembly) 或 wwwroot/css/site.css (Blazor Server) css文件中添加自定的样式或则使用框架Bootstrap和tailwindcss定义的css; 创建一个从 FieldCssClassProvider 派生的类,用于检查字段验证消息,并应用相应的有效或无效样式。

1
2
3
4
5
6
7
8
9
10
11
12
using System.Linq;
using Microsoft.AspNetCore.Components.Forms;

namespace BlazorAssmeblyNoHost.Options;
public class CustomFieldClassProvider : FieldCssClassProvider
{
    public override string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier)
    {
        var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
        return isValid ? "validField" : "invalidField";
    }
}

重写OnInitialized()方法设置自定义CSS属性提供器

1
2
3
4
5
6
7
8
9
@code{
protected override void OnInitialized()
{
editContext=new EditContext(holodeck);
editContext.SetFieldCssClassProvider(new CustomFieldClassProvider());
editContext.OnValidationRequested+=HandleValidationRequested;
messageStore=new(editContext);
}
}

参考

Blazor forms and validation

本文由作者按照 CC BY 4.0 进行授权
文章内容

Blazor 自定义组件

Blazor 状态管理