You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Server中Nullable Int的EditForm验证及点击事件异常

问题解决方案

问题1:Nullable Int空提交触发验证错误

原因

Blazor Server中使用[SupplyParameterFromForm]时,表单提交会将空字符串尝试绑定到int?类型属性,默认的InputNumber<int?>无法将空字符串解析为null,从而触发绑定验证错误。

解决方法

自定义适配int?的InputNumber组件,重写解析逻辑处理空字符串:

  1. 创建InputNullableInt.razor文件:
@inherits InputNumber<int?>

@code {
    protected override bool TryParseValueFromString(string? value, out int? result, out string? validationErrorMessage)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            result = null;
            validationErrorMessage = null;
            return true;
        }

        return base.TryParseValueFromString(value, out result, out validationErrorMessage);
    }
}
  1. 在Test页面中替换原InputNumber为自定义组件:
<InputNullableInt id="myNullableInt" class="form-control" @bind-Value="TestModel.MyNullableInt" />

空值提交时会自动将MyNullableInt设为null,且不会触发验证错误。


问题2:表格列头点击事件无法触发

原因

原代码将点击事件绑定在<span>标签上,可能因组件渲染状态不稳定或事件上下文问题导致失效;同时[SupplyParameterFromForm]触发的参数更新也可能影响事件绑定有效性。

解决方法

  1. 将点击事件直接绑定到<th>标签,添加交互样式确保可点击性:
<thead>
    <tr>
        <th role="button" style="cursor: pointer;" @onclick='() => ColumnHeaderClick("MyInt")'>Client</th>
        <th role="button" style="cursor: pointer;" @onclick='() => ColumnHeaderClick("MyString")'>My String</th>
    </tr>
</thead>
  1. (可选)为表格行添加@key稳定组件标识,避免重新渲染时事件绑定失效:
@foreach(var testSearchResult in TestSearchResults)
{
    <tr @key="testSearchResult.MyInt">
        <td>@testSearchResult.MyInt</td>
        <td>@testSearchResult.MyString</td>
    </tr>
}

修改后列头点击事件可正常触发,调用ColumnHeaderClick方法输出日志。


完整修改后的代码示例

@page "/Test"
@using Microsoft.Extensions.Logging
@inject ILogger<Test> _logger

<PageTitle>Test</PageTitle>

<h1>Test</h1>

@if(TestModel != null)
{
    <EditForm Model="TestModel" OnValidSubmit="HandleValidSubmit" FormName="TestModel1">
    <ValidationSummary />
    <div class="row g-3">
        <div class="col-md-4">
            <label for="myNullableInt" class="form-label">Nullable Int</label>
            <InputNullableInt id="myNullableInt" class="form-control" @bind-Value="TestModel.MyNullableInt" />
        </div>
        <div class="col-md-4">
            <label for="myString" class="form-label">Nullable String</label>
            <InputText id="myString" class="form-control" @bind-Value="TestModel.MyString" />
        </div>
        <div class="col-md-4">
            <label for="MyInt" class="form-label">Int</label>
            <InputNumber id="MyInt" class="form-control" @bind-Value="TestModel.MyInt" />
        </div>
    </div>
    <div class="mt-3">
        <button type="submit" class="btn btn-primary">Search</button>
    </div>
       
    </EditForm>
}

@if(TestSearchResults != null)
{
    <div class="mt-4">
        <table class="table table-striped">
            <thead>
                <tr>
                    <th role="button" style="cursor: pointer;" @onclick='() => ColumnHeaderClick("MyInt")'>Client</th>
                    <th role="button" style="cursor: pointer;" @onclick='() => ColumnHeaderClick("MyString")'>My String</th>
                </tr>
            </thead>
            <tbody>
                @foreach(var testSearchResult in TestSearchResults)
                {
                    <tr @key="testSearchResult.MyInt">
                        <td>@testSearchResult.MyInt</td>
                        <td>@testSearchResult.MyString</td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
}

@code {
    [SupplyParameterFromForm]
    public TestForm? TestModel { get; set; }
    private List<TestSearchResult>? TestSearchResults;


    protected override async Task OnInitializedAsync()
    {
        TestModel = TestModel ?? new TestForm();
        _logger.LogInformation("In OnInitializedAsync");
    }

    private async Task ColumnHeaderClick(string columnName)
    {
        _logger.LogInformation($"ColumnHeaderClick {columnName}");
    }

    private async Task HandleValidSubmit()
    {
        _logger.LogInformation("In HandleValidSubmit");

        TestSearchResults = new List<TestSearchResult>();
        for (int i = TestModel.MyNullableInt.GetValueOrDefault(); i < 100; i++ )
        {
            TestSearchResults.Add(new TestSearchResult()
                {
                    MyInt = i,
                    MyString = $"MyName{i}"

                });
        }
    }

    public class TestForm
    {
        public int MyInt { get; set; }

        public int? MyNullableInt { get; set; }

        public string? MyString { get; set; }
    }

    public class TestSearchResult
    {
        public int MyInt { get; set; }
        public string MyString { get; set; } = string.Empty;
    }
}

(配套InputNullableInt.razor代码如前文所述)

内容的提问来源于stack exchange,提问作者Tom Regan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 13:22:14