Blazor和fluentvalidation清除验证消息。

huangapple go评论57阅读模式
英文:

Blazor and fluentvalidation clear validation messages

问题

我有一个非常简单的模型,有一个开始时间和结束时间:

public class OutputModel
{
   public event Action<double> OnStartChanged;
   public event Action<double> OnEndChanged;
   public double Start { get; private set; }
   public double End { get; private set; }
   public string StartProxy { get; set; }
   public string EndProxy { get; set; }
}

我使用EditForm来显示输入框,用户可以编辑这些时间。输入框与StartProxy和EndProxy属性绑定,以便我可以在开始或结束框中输入有效时间时触发事件。

<EditForm Model="@Model">
    <div class="m-2 selector">
        <FluentValidationValidator @ref="Model.Validator" />

        <div class="info-group mb-1">
            <label for="start">Start</label>
            <InputText id="start" class="form-control form-control-sm" Value="@Model.StartProxy" ValueChanged="Model.StartChanged" ValueExpression="() => Model.StartProxy" />
        </div>
        <ValidationMessage For="() => Model.StartProxy" />

        <div class="info-group mb-1">
            <label for="end">Einde</label>
            <InputText id="end" class="form-control form-control-sm" Value="@Model.EndProxy" ValueChanged="Model.EndChanged" ValueExpression="() => Model.EndProxy" />
        </div>
        <ValidationMessage For="() => Model.EndProxy" />

        <div class="info-group mb-1">
            <label for="duration">Duur</label>
            <input id="duration" disabled="true" class="form-control form-control-sm" @bind="Model.Duration">
        </div>
    </div>
</EditForm>

这样做也需要我手动验证。因此,我创建了4个规则集,当StartProxy或EndProxy更改时手动调用:

  1. 用于检查StartProxy格式的规则集
  2. 用于检查EndProxy格式的规则集
  3. 用于检查Start是否在End之前的规则集
  4. 用于检查End是否在Start之后的规则集

我有3和4是因为我想要根据用户当前使用的框在开始框和结束框显示不同的消息。

验证开始的代码如下(结束类似,但属性不同):

public void StartChanged(string value)
{
    StartProxy = value;
    var validator = new OutputModelValidator();

    // 首先检查开始的格式
    var result = validator.Validate(this, options => options.IncludeRuleSets(OutputModelValidator.StartFormatRules));
    if (result.Errors.Any())
    {
        return;
    }

    // 如果格式正确,则可以设置开始时间
    Start = StartProxy.ToTimeSpan().Value.TotalSeconds;
    StartProxy = TimeSpan.FromSeconds(Start).ToString(TimeFormat);
    SetDuration();

    // 检查结束是否正确
    if (validator.Validate(this, options => options.IncludeRuleSets(OutputModelValidator.EndFormatRules)).Errors.Any())
    {
        // 结束有错误,所以我们结束这里
        return;
    }

    // 开始和结束的格式都正确,现在从结束的角度检查它们的组合
    if (!validator.Validate(this, options => options.IncludeRuleSets(OutputModelValidator.StartBeforeEndRules)).Errors.Any())
    {
        // 开始和结束都不错,所以传播值
        OnStartChanged?.Invoke(Start);
        OnEndChanged?.Invoke(End);
    }
}

所以首先我检查更改的框的格式。如果有效,我检查“其他”框是否包含错误(因为两者当然都可能错误)。当检查通过后,我检查开始和结束的组合。

基本上这很好用,但问题是:

  1. 结束框显示:“00:25.200”
  2. 我在开始框中输入:“00:30.123”
  3. 代码验证并在开始框中显示错误:“开始不在结束之后”
  4. 现在我在结束框中输入:“00:35.200”
  5. 代码验证并一切正常。
  6. 我的开始框仍然显示消息:“开始不在结束之后”

因此,我的问题是:我如何清除“其他”属性的消息。还是我需要完全不同的方法。当然欢迎建议。非常感谢。

英文:

I have a very simple model with a starttime and endtime:

public class OutputModel
{
   public event Action&lt;double&gt; OnStartChanged;
   public event Action&lt;double&gt; OnEndChanged;
   public double Start { get; private set; }
   public double End { get; private set; }
   public string StartProxy { get; set; }
   public string EndProxy { get; set; }
}

I'm using an EditForm to display inputboxes in which the user can edit these times. The inputboxes are bind to the StartProxy and EndProxy properties in such a way that I can trigger the events whenever a valid time is entered in either the start or end box.

&lt;EditForm Model=&quot;@Model&quot;&gt;
    &lt;div class=&quot;m-2 selector&quot;&gt;
        &lt;FluentValidationValidator @ref=&quot;Model.Validator&quot; /&gt;

        &lt;div class=&quot;info-group mb-1&quot;&gt;
            &lt;label for=&quot;start&quot;&gt;Start&lt;/label&gt;
            &lt;InputText id=&quot;start&quot; class=&quot;form-control form-control-sm&quot; Value=&quot;@Model.StartProxy&quot; ValueChanged=&quot;Model.StartChanged&quot; ValueExpression=&quot;() =&gt; Model.StartProxy&quot; /&gt;
        &lt;/div&gt;
        &lt;ValidationMessage For=&quot;() =&gt; Model.StartProxy&quot; /&gt;

        &lt;div class=&quot;info-group mb-1&quot;&gt;
            &lt;label for=&quot;end&quot;&gt;Einde&lt;/label&gt;
            &lt;InputText id=&quot;end&quot; class=&quot;form-control form-control-sm&quot; Value=&quot;@Model.EndProxy&quot; ValueChanged=&quot;Model.EndChanged&quot; ValueExpression=&quot;() =&gt; Model.EndProxy&quot; /&gt;
        &lt;/div&gt;
        &lt;ValidationMessage For=&quot;() =&gt; Model.EndProxy&quot; /&gt;

        &lt;div class=&quot;info-group mb-1&quot;&gt;
            &lt;label for=&quot;duration&quot;&gt;Duur&lt;/label&gt;
            &lt;input id=&quot;duration&quot; disabled=&quot;true&quot; class=&quot;form-control form-control-sm&quot; @bind=&quot;Model.Duration&quot;&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/EditForm&gt;

Doing this also requires me to validate things manually. So I have created 4 rulesets which I call manually when either StartProxy or EndProxy changes:

  1. A ruleset to check the format of StartProxy
  2. A ruleset to check the format of EndProxy
  3. A ruleset to check if Start is before End
  4. A ruleset to check if End is after Start

I have 3 and 4 because I want different messages at the startbox and endbox depending on the box that is currently used by the user.

The code that validates the start is this (the end is more or less the same, but different properties):

public void StartChanged(string value)
{
    StartProxy = value;
    var validator = new OutputModelValidator();

    // First check the format of the start
    var result = validator.Validate(this, options =&gt; options.IncludeRuleSets(OutputModelValidator.StartFormatRules));
    if (result.Errors.Any())
    {
        return;
    }

    // Start can be set if the format is ok
    Start = StartProxy.ToTimeSpan().Value.TotalSeconds;
    StartProxy = TimeSpan.FromSeconds(Start).ToString(TimeFormat);
    SetDuration();

    // Check if end is correct
    if (validator.Validate(this, options =&gt; options.IncludeRuleSets(OutputModelValidator.EndFormatRules)).Errors.Any())
    {
        // End contains errors, so were done here
        return;
    }

    // Start and end are &#39;format valid&#39;, now check their combination from an end perspective
    if (!validator.Validate(this, options =&gt; options.IncludeRuleSets(OutputModelValidator.StartBeforeEndRules)).Errors.Any())
    {
        // Start is good and end is good so propagate the values
        OnStartChanged?.Invoke(Start);
        OnEndChanged?.Invoke(End);
    }
}

So first I'm checking the format of the box that is changed. When valid I check if the 'other' box contains errors (because both can be wrong ofcourse). When good, then I check the combination for start and end.

In basic this works fine, but the problem is the following:

  1. The endbox shows: '00:25.200'
  2. I type '00:30.123' in the startbox
  3. The code validates and gives an error at the startbox: 'Start not after end'
  4. I now type '00:35.200' in the endbox
  5. The code validates and everything is fine.
  6. My startbox still shows the message: 'Start not after end'

So my question is: how can I clear the messages for the 'other' property. Or do I need a completely different approach. Suggestions are welcome ofcourse.

Many thanks in advance

答案1

得分: 0

Sure, here's the translated code part:

在不断搜索和搜索,以及更多的搜索之后(并在此线程中找到答案:https://stackoverflow.com/questions/60917323/how-to-reset-custom-validation-errors-when-using-editform-in-blazor-razor-page),我终于修复了这个问题。

首先,我的问题出在与编辑表单的绑定上。我之前写的是:

&lt;EditForm Model=&quot;@Model&quot;&gt;

应该改成:

&lt;EditForm EditContext=&quot;@Model.EditContext&quot;&gt;

然后,在所有验证完成后,我现在调用:

EditContext.NotifyFieldChanged(new FieldIdentifier(this, nameof(StartProxy)));

这样告诉 Blazor 更新其他字段(在本例中是 StartProxy)。

英文:

After searching and searching and much more searching (and finding the answers in this thread: https://stackoverflow.com/questions/60917323/how-to-reset-custom-validation-errors-when-using-editform-in-blazor-razor-page) I finally was able to fix this.

First problem was my binding to the editform. I had this:

&lt;EditForm Model=&quot;@Model&quot;&gt;

which should be this:

&lt;EditForm EditContext=&quot;@Model.EditContext&quot;&gt;

Then in the code after all the validations are done I now call this:

EditContext.NotifyFieldChanged(new FieldIdentifier(this, nameof(StartProxy)));

So you tell Blazor to update the other field (in this case StartProxy).

huangapple
  • 本文由 发表于 2023年6月13日 02:33:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76459397.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定