Skip to content

Validation modes, summary & reset

Choose when a field revalidates, independently for before and after the first submit — the same mode/reValidateMode split React Hook Form popularised. The summary below lists every error in schema order and links to the control that needs fixing. The username field is debounced, so its async availability check runs once you pause rather than once per character — try ada or admin and watch the indicator below.

Live form
Create your account

Try 'ada' or 'admin' to see the async rule fire.

dirty: False · submitted: 0 time(s) · saved: False · errors: 0 · checking username: no

View source
@page "/validation"
@inject DemoDirectory Directory

<BormView State="_state"
          ReadOnly="_readOnly"
          ShowErrorSummary="true"
          ShowResetButton="true"
          OnValidSubmit="HandleSubmit"
          SubmitText="Create account" />

@code {
    private readonly NewAccount _model = new();
    private BormState _state = default!;
    private bool _readOnly;

    protected override void OnInitialized()
    {
        var schema = BormBuilder.For<NewAccount>()
            .Title("Create your account")
            .Field(x => x.Email, f => f.Autocomplete("email"))
            .Field(x => x.Username, f => f
                .Required()
                .Autocomplete("username")
                .Trim()                                  // fix the value; do not complain about spaces
                // Debouncing writes once per pause instead of once per character — and the async rule
                // runs with that write, which is the whole reason to debounce a field that calls out
                // to a service. An undebounced field's async rules still wait for blur.
                .UpdateOnInput(debounceMilliseconds: 400)
                .MustAsync(async ctx => await Directory.IsUsernameAvailableAsync((string?)ctx.Value ?? "", ctx.CancellationToken),
                           "That username is taken.")
                .Help("Try 'ada' or 'admin' to see the async rule fire."))
            .Field(x => x.Password, f => f.Autocomplete("new-password"))
            // [Compare] on the model already wires the confirm rule.
            .Field(x => x.ConfirmPassword, f => f.Autocomplete("new-password"))
            .Build();

        _state = new BormState(schema, new BormModelDataAccessor(_model))
        {
            // Stay quiet until the first submit, then correct eagerly.
            ValidationTrigger = BormValidationTrigger.OnBlur,
            RevalidationTrigger = BormValidationTrigger.OnChange
        };
        _state.StateChanged += OnStateChanged;
    }
}
An unhandled error has occurred. Reload 🗙