aspnet-client-validation
aspnet-client-validation copied to clipboard
Remote validator strange behavior
I encountered a strange behavior for the Remote validator.
After the remote validator fire, regardless of the result, the form is posted even if the form is invalid.
It seem the preventDefault and the stopPropagation of the submit event is skipped, but I cannot understand how to fix it.
@page
@model IndexModel
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<form method="post">
<label asp-for="Id"></label>
<input asp-for="Id" />
<span asp-validation-for="Id"></span>
<label asp-for="Control"></label>
<input asp-for="Control" />
<span asp-validation-for="Control"></span>
<button type="submit">Save</button>
</form>
<script src="aspnet-validation.js"></script>
<script>
const service = new aspnetValidation.ValidationService();
service.bootstrap();
</script>
</body>
</html>
public class IndexModel : PageModel
{
[BindProperty]
[Required]
[Remote("CheckRemote", "Validations", HttpMethod = "Post")]
public string Id { get; set; }
[BindProperty]
[Required]
public string Control { get; set; }
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return BadRequest();
}
return Content("OK");
}
}
[ApiController]
[Route("api/[controller]")]
public class ValidationsController : ControllerBase
{
[HttpPost]
[Route("check-remote")]
public IActionResult CheckRemote()
{
bool isValid = false;
return Ok(isValid);
}
}
Maybe is a timing problem.
The preventDefault and StopImmediatePropagation calls are inside the validate.then() promise. The submit event is not prevented, and while the validator is waiting for response from remote, the submit event is captured and processed and the page is posted.
...
var cb = function (e, callback) {
var validate = _this.getFormValidationTask(formUID);
if (!validate) {
return;
}
validate.then(function (success) {
var isProgrammaticValidate = !e;
if (success) {
if (isProgrammaticValidate) {
callback(true);
return;
}
var validationEvent_1 = new CustomEvent('validation', {
detail: { valid: true }
});
form.dispatchEvent(validationEvent_1);
return;
}
//This here is inside a promise and cannot prevent in time the submit event
if (e) {
e.preventDefault();
e.stopImmediatePropagation();
}
var validationEvent = new CustomEvent('validation', {
detail: { valid: false }
});
form.dispatchEvent(validationEvent);
if (isProgrammaticValidate) {
callback(false);
}
else {
_this.focusFirstInvalid(form);
}
}).catch(function (error) {
console.log(error);
});
};
...
...
var cb = function (e, callback) {
var validate = _this.getFormValidationTask(formUID);
if (!validate) {
return;
}
//Moved here to prevent the submit before validation
if (e) {
e.preventDefault();
e.stopImmediatePropagation();
}
validate.then(function (success) {
var isProgrammaticValidate = !e;
if (success) {
if (isProgrammaticValidate) {
callback(true);
return;
}
var validationEvent_1 = new CustomEvent('validation', {
detail: { valid: true }
});
form.dispatchEvent(validationEvent_1);
// Had to resubmit the form here, but I don't know if it is correct. I don't know if I have to capture the validation CustomEvent and resubmit from there.
form.submit();
return;
}
var validationEvent = new CustomEvent('validation', {
detail: { valid: false }
});
form.dispatchEvent(validationEvent);
if (isProgrammaticValidate) {
callback(false);
}
else {
_this.focusFirstInvalid(form);
}
}).catch(function (error) {
console.log(error);
});
};
...
Do you have an idea on how I should fix it?
I moved the preventDefault outside the validate Promise, then resubmit the form if the validation has succeded.
If you look at my last comment all the fix i did is there.