mardi 11 juin 2019

Validation no longer works properly when I use setCustomValidity on grouped checkboxes

I have a web application for which I'm trying to control form validation programmatically and I'm running into some issues.

Why programmatically? Because there doesn't seem to be a way to set a checkbox group to "required" (I can set each individual checkbox to "required" but not the group). So this is what I've done:

<fieldset>
                        <legend class="checkbox-group-legend">What brings you to Calgary?</legend>
                        <div class="checkbox-group">
                            <div class="row">
                                <div class="col-sm-6 col-xs-12">
                                    <input type="checkbox" group="reason" id="vacation" name="vacation" onclick="reasonForVisitingChecked()" required>Vacation
                                </div>
                                <div class="col-sm-6 col-xs-12">
                                    <input type="checkbox" group="reason" id="business" name="business" onclick="reasonForVisitingChecked()" required>Business
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-sm-6 col-xs-12">
                                    <input type="checkbox" group="reason" id="liveHere" name="liveHere" onclick="reasonForVisitingChecked()" required>Live Here
                                </div>
                                <div class="col-sm-6 col-xs-12">
                                    <input type="checkbox" group="reason" id="other" name="other" onclick="reasonForVisitingChecked()" required>Other
                                </div>
                            </div>
                        </div>
                    </fieldset>

Javascript:

    function reasonForVisitingChecked() {
        var reasonForVisitingCheckboxes = $("input:checkbox[group='reason']");
        reasonForVisitingCheckboxes.prop('required', true);
        for (var i = 0; i < reasonForVisitingCheckboxes.length; i++) {
            if ($(reasonForVisitingCheckboxes[i]).is(':checked')) {
                reasonForVisitingCheckboxes.prop('required', false);
                break;
            }
        }
    }

I got this trick from here:

Using the HTML5 "required" attribute for a group of checkboxes?

This works great... except now I get a very misleading validation message when no checkbox is check:

enter image description here

It points to the "vacation" checkbox and tells the user to check that one.

So I looked up ways to change the validation error message, and I stumbled across this:

https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/setCustomValidity

This says to use setCustomValidity(string) as follows:

<fieldset>
                        <legend class="checkbox-group-legend">What brings you to Calgary?</legend>
                        <div class="checkbox-group">
                            <div class="row">
                                <div class="col-sm-6 col-xs-12">
                                    <input type="checkbox" group="reason" id="vacation" name="vacation" onclick="reasonForVisitingChecked()" oninvalid="this.setCustomValidity('Please select at least one checkbox.')" onvalid="this.setCustomValidity('')" required>Vacation
                                </div>
                                <div class="col-sm-6 col-xs-12">
                                    <input type="checkbox" group="reason" id="business" name="business" onclick="reasonForVisitingChecked()" oninvalid="this.setCustomValidity('Please select at least one checkbox.')" onvalid="this.setCustomValidity('')" required>Business
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-sm-6 col-xs-12">
                                    <input type="checkbox" group="reason" id="liveHere" name="liveHere" onclick="reasonForVisitingChecked()" oninvalid="this.setCustomValidity('Please select at least one checkbox.')" onvalid="this.setCustomValidity('')" required>Live Here
                                </div>
                                <div class="col-sm-6 col-xs-12">
                                    <input type="checkbox" group="reason" id="other" name="other" onclick="reasonForVisitingChecked()" oninvalid="this.setCustomValidity('Please select at least one checkbox.')" onvalid="this.setCustomValidity('')" required>Other
                                </div>
                            </div>
                        </div>
                    </fieldset>

This also works great... except now the validation error message won't go away even when I check one or more checkboxes and hit submit. It's as if my function for removing the "required" attribute is working but it's not undoing the invalid state of the checkboxes... but then again, how did it work without the calls to setCustomValidity(...)?

So here's the problem: I need to put some kind of "required" attribute on the checkbox group (not individual checkboxes) such that the user must check at least one checkbox. My function above for toggling the "required" attribute when at least one checkbox is checked works but leaves me with a mislead validation error message. The call to setCustomValidaty(...) fixes the misleading message but won't go away when one or more checkboxes are check (and in fact won't allow the form to be submitted).

Please help. Thanks.




Aucun commentaire:

Enregistrer un commentaire