question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Validation occurs before binding completes when using a custom Razor component whose custom binding needs to call JSInterop

See original GitHub issue

I encountered this issuing when using this IntlTelInput component, which is a Blazor wrapper for intl-tel-input, a popular phone number validator js library.

The IntlTelInput Razor component wraps a basic input component like this:

<input @onchange="OnChange" type="tel" @ref="_telInput"/>

private async void OnChange (ChangeEventArgs e)
{
    CurrentValue = await _intlTelInputJsInterop.GetData(_inputIndex);
    if (CurrentValue is not null)
    {
        await _intlTelInputJsInterop.SetNumber(_inputIndex, CurrentValue.Number);
     }
}

And I use the IntlTelInput component itself in an EditForm like this:

<EditForm EditContext="_editContext" OnValidSubmit="OnValidSubmit" OnInvalidSubmit="OnInvalidSubmit">
    
    <FluentValidationValidator DisableAssemblyScanning="@true" />
    <ValidationSummary/>
        
    <IntlTelInput @bind-Value="_model.IntTelNumber"/>
        
    <button class="btn-primary">Submit</button>

</EditForm>

Note that the bound property model.IntTelNumber is not a string , but a custom type IntlTel. It is constructed by the JSInterop call as shown earlier. The object then exposes a Number property (for the phone number) and a IsValid property which represents the result of the number validation by intl-tel-input. My FluentValidation code in turn uses this IsValid property like this:

 RuleFor(x => x.IntTelNumber).Cascade(CascadeMode.Stop)
                .NotNull()
                .WithMessage("Please enter a phone number")
                .Must( x => x.IsValid)
                .WithMessage("Invalid phone number")

So here’s the problem:

Whenever a user enters a number, and immediately click the submit button, the OnChange event handler in the Razor component triggers, which is supposed to call JSInterop and assign the generated object to model.IntTelNumber. But before this completes, the FluentValidation code already triggers, and at this time, it sees IntTelNumber as null, and therefore this validation fails.

After the JSInterop call completes, the FluentValidation code appears to trigger again, this time validating the property property.

The more bizarre part is, on a desktop browser, the first “failed validation” occurs so fast (can be only seen while debugging) that in the actual EditForm, OnValidSubmit is actually triggered. So everything turns out fine and the form validates normally.

But on any mobile browser, OnInvalidSubmit is triggered instead. The result is that the first time user enters the phone number and hits the submit button, the form does not submit. But if the user simply hits the button again, it validates property and submits the form.

I wonder if there is anything that can be done to mitigate this issue. Any advice would be greatly appreciated.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
Lierocommented, Oct 1, 2021

@chrissainty: this is not related to async validation.

@mikequ-taggysoft: the problem is, that the OnChange handler should be async Task and not async void. You must open issue in the https://github.com/R0landas/intl-tel-input-blazor project

0reactions
Lierocommented, Oct 2, 2021

@mikequ-taggysoft: oh, I see why. It should be something like:

CurrentValue = await _intlTelInputJsInterop.SetNumber(_inputIndex, CurrentValue.Number);

It is not optimal, but it is _intlTelInputJsInterop’s ussye.

Read more comments on GitHub >

github_iconTop Results From Across the Web

[Bug] Async Validator not working correctly · Issue #38
Validation occurs before binding completes when using a custom Razor component whose custom binding needs to call JSInterop #79.
Read more >
Handle errors in ASP.NET Core Blazor apps
This article describes how Blazor manages unhandled exceptions and how to develop apps that detect and handle errors.
Read more >
JS Interop - Working with JavaScript in Blazor
In this tutorial we are going to cover the whole process of JS Interop in Blazor by taking multiple examples. IJSRuntime Interface. Calling...
Read more >
How to bind to document events with Blazor
Use JavaScript for binding and invoke Blazor code (taken from https://github.com/aesalazar/AsteroidsWasm):. document.onkeydown = function (evt) ...
Read more >
Blazor manualresetevent. Close [] This method is the public ...
The Blazor Component Event handler calls StateHasChanged and yields. ... To be able to use @bind-Value you need two parameters, T Value and...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found