Blazor 如何使输入组件验证输入并调用指定的回调?
我想要一些像:Blazor 如何使输入组件验证输入并调用指定的回调?,blazor,blazor-webassembly,Blazor,Blazor Webassembly,我想要一些像: <input id=filterString type="number" class="form-control" value="@FilterModel.FilterString" @oninput="@FilterChanged" /> 但是,要利用 到目前为止,我遇到的最简单和最接近的解决方案(也许?)可能是创建InputBase子类的方法,将指定的回调作为参数传递,并在调用I
<input id=filterString type="number" class="form-control" value="@FilterModel.FilterString" @oninput="@FilterChanged" />
但是,要利用
到目前为止,我遇到的最简单和最接近的解决方案(也许?)可能是创建InputBase子类的方法,将指定的回调作为参数传递,并在调用InputBase的ValueChanged
的同时调用它。类似于
我无法让它工作(我无法具体回忆错误,但如果推荐使用这种方法,我可以在以后检索它们),并且在反复排除故障后,它开始感觉笨拙。我浏览了文档,但仍然不明白验证系统和绑定是如何结合在一起的。所以我有点迷路了,希望能有人帮我整理一下
总而言之:
InputNumber
(或等效)的最简单方法,其中我还可以指定OnInput
(或等效)回调,以便在值更改时执行一些工作谢谢,非常感谢您的帮助。您可以创建自己的组件并接收类型为
EditContext
的级联参数-然后您可以使用该参数调用验证,并获取字段的任何验证消息
现在您已经完全控制了输入,可以挂接到它的@oninput
方法并执行您的工作(引发其他事件,执行更多逻辑,调用编辑上下文的.Validate()
方法)
您可能需要添加更多的参数以允许值表达式,可能需要输入param,可能需要字段名的标识符,诸如此类,以使其更具可重用性和通用性,但核心是获取编辑上下文并控制您自己的呈现和事件
编辑:添加示例-请注意,这只是一个实现,它既不是通用的,也不是完美的
与表单一起使用的主要组件
@使用System.ComponentModel.DataAnnotations
@model.MyProperty
@代码{
MyFormModel模型{get;set;}=new MyFormModel();
异步任务MySpecialEventHandler(日期时间)
{
WriteLine($“在:{time.millis秒}触发的特殊事件”);
}
公共类MyFormModel
{
[必需]
[射程(3,5)]
公共int?MyProperty{get;set;}
}
}
子组件-MyNumberInput
@实现IDisposable
@代码{
[CascadingParameter]
公共EditContext TheEditContext{get;set;}
[参数]
公共字段标识符FieldId{get;set;}
[参数]
公共int?值{get;set;}
[参数]
public EventCallback ValueChanged{get;set;}
[参数]
public EventCallback MySpecialEvent{get;set;}
InPurtHandler上的异步任务(ChangeEventArgs e)
{
尝试
{
int val=int.Parse(例如Value.ToString());
值=val;
}
抓住
{
值=空;
}
//双向装订
wait ValueChanged.InvokeAsync(值);
//更新验证-值保存在表单中后
TheEditContext.NotifyFieldChanged(FieldId);
//根据需要选择您自己的活动
等待MySpecialEvent.InvokeAsync(DateTime.Now);
}
//可能不需要一些常规更新,但如果其他字段更新此字段并且您需要重新提交,则可能会有所帮助
无效ValidationStateChanged(对象发送方,ValidationStateChangedEventArgs e)
{
StateHasChanged();
}
受保护的覆盖无效OnInitialized()
{
如果(TheEditContext!=null)
TheEditContext.OnValidationStateChanged+=ValidationStateChanged;
}
公共空间处置()
{
如果(TheEditContext!=null)
TheEditContext.OnValidationStateChanged-=ValidationStateChanged;
}
}
事件的顺序有点像
哇,你真是个飞天高手。我也在这里。嗯,你能给我发个代码示例吗?我很难想象如何把它组合起来。感谢您澄清事件的顺序。我为您制作了一个,帖子是edited@rdmptnAFAICT此方法专门用于使
EditForm
(或只是一般的表单)更容易、更方便地实现、自定义和扩展等。。不幸的是,我认为这可能不是我想要的东西(使用表格),因为我的输入不打算在填写后立即提交,而是在每次更改后立即使用;我认为对于这一点,输入字段(而不是表单)才是工作的正确“工具”。我说得对吗?思维方式不是我在这里的正确工具?如果是这样的话,是否可以在没有EditForm
的情况下执行此操作?您最初的帖子讨论了InputNumber和其他与表单相关的组件,因此我认为您需要它。如果你没有,可以放下所有这些,直接处理@oninput
。只需更新视图模型-您仍然需要该值,否则每次击键都会丢失该值,用户将无法输入多个数字的数字。
@using System.ComponentModel.DataAnnotations
<EditForm Model="@TheModel">
<DataAnnotationsValidator></DataAnnotationsValidator>
@TheModel.MyProperty
<br />
<MyNumberInput @bind-Value="@TheModel.MyProperty"
MySpecialEvent="@MySpecialEventHandler"
FieldId="@( new FieldIdentifier(TheModel, nameof(MyFormModel.MyProperty)) )" />
<ValidationMessage For="@( () => TheModel.MyProperty )"></ValidationMessage>
</EditForm>
@code{
MyFormModel TheModel { get; set; } = new MyFormModel();
async Task MySpecialEventHandler(DateTime time)
{
Console.WriteLine($"special event fired at: {time.Millisecond}");
}
public class MyFormModel
{
[Required]
[Range(3, 5)]
public int? MyProperty { get; set; }
}
}
@implements IDisposable
<input type="number" @oninput="@OnInputHandler" value="@Value" />
@code {
[CascadingParameter]
public EditContext TheEditContext { get; set; }
[Parameter]
public FieldIdentifier FieldId { get; set; }
[Parameter]
public int? Value { get; set; }
[Parameter]
public EventCallback<int?> ValueChanged { get; set; }
[Parameter]
public EventCallback<DateTime> MySpecialEvent { get; set; }
async Task OnInputHandler(ChangeEventArgs e)
{
try
{
int val = int.Parse(e.Value.ToString());
Value = val;
}
catch
{
Value = null;
}
//twoway binding
await ValueChanged.InvokeAsync(Value);
//update validation - AFTER the value is saved in the form
TheEditContext.NotifyFieldChanged(FieldId);
//your own event as needed
await MySpecialEvent.InvokeAsync(DateTime.Now);
}
//some general update that may not be needed but might help if other fields update this one and you need to rerender
void ValidationStateChanged(object sender, ValidationStateChangedEventArgs e)
{
StateHasChanged();
}
protected override void OnInitialized()
{
if (TheEditContext != null)
TheEditContext.OnValidationStateChanged += ValidationStateChanged;
}
public void Dispose()
{
if (TheEditContext != null)
TheEditContext.OnValidationStateChanged -= ValidationStateChanged;
}
}