Home > database >  How can I apply Bootstrap 5 validation to a Razor form?
How can I apply Bootstrap 5 validation to a Razor form?

Time:08-28

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>
  • Related