I have Razor Pages form like this:
<form id="account" method="post">
<div asp-validation-summary="ModelOnly" ></div>
<div >
<input asp-for="Input.Email" autocomplete="username" aria-required="true" />
<label asp-for="Input.Email" ></label>
<span asp-validation-for="Input.Email" ></span>
</div>
...
in the output i get the following render:
<form id="account" method="post">
<div >
<input autocomplete="username" aria-required="true" type="email" data-val="true"
data-val-email="The Email field is not a valid e-mail address." data-val-required="The Email field is required."
id="Input_Email" name="Input.Email" value="">
<label for="Input_Email">Email</label>
<span data-valmsg-for="Input.Email" data-valmsg-replace="true"></span>
</div>
...
But Bootstrap v5 uses the :invalid
and :valid
styles applied to form controls.
At the same time, data-val-
attributes are not taken into account in any way.
Is it possible to seamlessly connect the Bootstrap 5 validation functionality on the client while retaining all the power of customizing the Razor Pages validation model?
CodePudding user response:
After reading the documentation for the ValidityState object and the JS Forms API. And by combining this with Bootstrap Validation, we got the following solution for the following validation properties: valueMissing
, typeMismatch
(email), tooLong
, tooShort
. The list is not complete, the solution can be developed to suit your needs.
<script type="text/javascript">
(() => {
'use strict'
function validateControl(c) {
c.addEventListener('input', (event) => setErrMessage(c));
}
function setErrMessage(c) {
const name = c.getAttribute('name');
const errMsg = Array.from(c.parentElement
.querySelectorAll(`[data-valmsg-for="${name}"]`))
.filter(msg => !!msg.getAttribute('data-valmsg-replace'));
errMsg.forEach(msg => msg.innerText = '');
c.required = !!c.getAttribute('aria-required');
const requiredErrorMessage = c.getAttribute('data-val-required');
if (requiredErrorMessage && c.validity.valueMissing)
errMsg.forEach(msg => msg.innerText = requiredErrorMessage);
const typeMismatchErrorMessage = c.getAttribute('data-val-email');
if (typeMismatchErrorMessage && c.validity.typeMismatch)
errMsg.forEach(msg => msg.innerText = typeMismatchErrorMessage);
const lengthMax = c.getAttribute('data-val-length-max');
const lengthMin = c.getAttribute('data-val-length-min');
if (lengthMin)
c.setAttribute('minlength', lengthMin)
const lengthErrorMessage = c.getAttribute('data-val-length');
if (lengthErrorMessage && (c.validity.tooLong || c.validity.tooShort))
errMsg.forEach(msg => msg.innerText = lengthErrorMessage);
}
// Fetch all the forms we want to apply custom Bootstrap validation styles to
const forms = document.querySelectorAll('form')
// Loop over them and prevent submission
Array.from(forms).forEach(form => {
form.noValidate = true;
const controls = form.querySelectorAll('[data-val="true"]');
Array.from(controls).forEach(validateControl);
form.addEventListener('submit', event => {
Array.from(controls).forEach(setErrMessage);
const isValid = form.checkValidity();
if (!isValid) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>