Open jlarc opened 7 years ago
Thank you for this pull request.
Unfortunately, I have tried that exact technique which you posted in the past. I'll explain briefly the problem in your solution:
https://github.com/ryanelian/aspnet-validation/blob/master/src/index.ts#L725
If you noticed, an input validator is a boolean Promise, an object which resolves asynchronously just like a C# Task<bool>
.
"Why bother making a Promise for an input validator? Why can't you just do the good-old-fashioned synchronous validation for inputs one-by one?"
Well, it's due to the existence of ASP.NET Core MVC Remote Validation, which fires an HTTP request to an API for server-side validation. It is asynchronous by nature.
Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchronous requests on the main thread have been deprecated due to the negative effects to the user experience. https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests#Example_HTTP_synchronous_request
By now you should already have an idea why I decided to first prevent the default submit event then submit later if indeed the inputs are valid. But I'll explain anyway:
Unfortunately, addEventListener
for DOM Element is blissfully unaware of the asynchronous world. If you fire asynchronous validations for all inputs on form submission event, this happens:
Hence we are unable to stop the form from submitting if an asynchronous validation failed. 💀
I'm sorry, your PR bugged when this was attempted (I tried your code to be sure):
Try inputting whatever then click the submit button.
Test.cshtml.cs
public class TestModel : PageModel
{
[Required]
[StringLength(255)]
[Remote("Get", "TestApi")]
public string Test { set; get; }
public void OnGet()
{
}
}
Test.cshtml
@page
@model TestModel
@{
}
<h3>Test</h3>
<form method="post">
<div class="form-group">
<label asp-for="Test"></label>
<input asp-for="Test" class="form-control" />
<span asp-validation-for="Test"></span>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
TestApiController.cs
[Produces("application/json")]
[Route("api/v1/test")]
public class TestApiController : Controller
{
[HttpGet]
public IActionResult Get(string test)
{
if (test == "jono")
{
return Ok(true);
}
else
{
return Ok("Input value must be 'jono'!");
}
}
}
That said, I am still willing to help you with this issue. Please describe in more detail what you're trying to solve. I'm open for discussion ☕️
This allows us to layer on Progressive Enhancement if we want to use js and fetch for example for async form posts.