At Least One Check Box Required

I have a checkbox group. I would like to make it so that at least one box has to be selected. How can I do that?

<div class="form-group" id="check_special_interest" is="dmx-checkbox-group">
                                                <legend class="col col-form-label">Special Interest</legend>
                                                <div class="form-check">
                                                    <input class="form-check-input" type="checkbox" value="Reg" id="si-reg" name="si-reg">
                                                    <label class="form-check-label" for="si-reg">Regular</label>
                                                </div>
                                                <div class="form-check">
                                                    <input class="form-check-input" type="checkbox" value="Y" id="si-youth" name="si-youth">
                                                    <label class="form-check-label" for="isi-youth">Youth</label>
                                                </div>
                                                <div class="form-check">
                                                    <input class="form-check-input" type="checkbox" value="MW" id="si-mw" name="si-mw">
                                                    <label class="form-check-label" for="si-mw">Mature Worker</label>
                                                </div>
                                                <div class="form-check">
                                                    <input class="form-check-input" type="checkbox" value="OW" id="si-ow" name="si-ow">
                                                    <label class="form-check-label" for="si-ow">Older Worker</label>
                                                </div>
                                                <div class="form-check">
                                                    <input class="form-check-input" type="checkbox" value="I" id="si-ind" name="si-ind">
                                                    <label class="form-check-label" for="si-ind">Indiginous</label>
                                                </div>
                                                <div class="form-check">
                                                    <input class="form-check-input" type="checkbox" value="IM" id="si-im" name="si-im">
                                                    <label class="form-check-label" for="si-im">IM?</label>
                                                </div>
                                            </div>

I was asked to help somebody with this just last week…Here’s what I came up with.

<dmx-array id="arr1"></dmx-array>
<form id="form1">
    <div class="form-group mb-3" is="dmx-checkbox-group" id="group1">
        <legend class="col-sm-2 col-form-label">One checkbox</legend>
        <div class="form-check">
            <input class="form-check-input" type="checkbox" value="1" id="input1" name="input1" dmx-bind:disabled="arr1.count==1 && checked" dmx-on:click="run({condition:{if:`arr1.items.contains(value)`,then:{steps:{run:{action:`arr1.remove(value)`}}},else:{steps:{run:{action:`arr1.addUniq(value)`}}}}})">
            <label class="form-check-label" for="input1">Single checkbox</label>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="checkbox" value="2" id="input2" name="input2" dmx-bind:disabled="arr1.count==1 && checked" dmx-on:click="run({condition:{if:`arr1.items.contains(value)`,then:{steps:{run:{action:`arr1.remove(value)`}}},else:{steps:{run:{action:`arr1.addUniq(value)`}}}}})">
            <label class="form-check-label" for="input2">Single checkbox</label>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="checkbox" value="3" id="input3" name="input3" dmx-bind:disabled="arr1.count==1 && checked" dmx-on:click="run({condition:{if:`arr1.items.contains(value)`,then:{steps:{run:{action:`arr1.remove(value)`}}},else:{steps:{run:{action:`arr1.addUniq(value)`}}}}})">
            <label class="form-check-label" for="input2">Single checkbox</label>
        </div>
    </div>
</form>

You have an array element that represents a list of all the checkbox id’s that are checked. If you page has checkboxes checked on load, then make sure those id’s are populated in the array at load. The value for each checkbox must be unique for this to work.

The last remaining checkbox that is checked, will be disabled, and thus prevents it from being unchecked. The other checkboxes may still be checked. It you don’t want it to look disabled, you can just add css for the :disabled selector for these checkboxes.

There is a problem with your solution. It indeed works that you disable the last checked checkbox, but when you submit the form the disabled inputs will not be send. If you do not submit the form then you could use it.

i have done this with a javascript before… but dont know the wappler way…

     <script>
    (function() {
        const form = document.querySelector('#sectionForm');
        const checkboxes = form.querySelectorAll('input[type=checkbox]');
        const checkboxLength = checkboxes.length;
        const firstCheckbox = checkboxLength > 0 ? checkboxes[0] : null;

        function init() {
            if (firstCheckbox) {
                for (let i = 0; i < checkboxLength; i++) {
                    checkboxes[i].addEventListener('change', checkValidity);
                }

                checkValidity();
            }
        }

        function isChecked() {
            for (let i = 0; i < checkboxLength; i++) {
                if (checkboxes[i].checked) return true;
            }

            return false;
        }

        function checkValidity() {
            const errorMessage = !isChecked() ? 'At least one checkbox must be selected.' : '';
            firstCheckbox.setCustomValidity(errorMessage);
        }

        init();
    })();
    </script>

You are correct, my solution was for a filter—it is not in a form that is ever submitted.

Is there a Wappler way to do this yet? I really need to set a required validation on a checkbox group so that at least one box is checked.

Any ideas?

Hey @brad,
Just pinched this from one of our old Projects, radio group though but similar principle should apply to a checkbox group? You can see the name for all the radios is the same but the id’s are different. As long as the names are the same and you apply validation to one of the radios the validation should work for all…

<form id="forBradForm">
                    <div class="col">

                        <label for="" class="color-highlight font-400 font-13">Type</label>
                        <div is="dmx-checkbox-group" id="typeGroup" class="radio-group mb-0">
                            <div class="form-check icon-check form-check-inline">
                                <input class="form-check-input" type="radio" name="Booking_Type" value="1" id="owner" required="">
                                <label class="form-check-label" for="owner">Owner</label>
                            </div>
                            <div class="form-check icon-check form-check-inline">
                                <input class="form-check-input" type="radio" name="Booking_Type" value="2" id="house">
                                <label class="form-check-label" for="house">In-House</label>
                            </div>
                            <div class="form-check icon-check form-check-inline">
                                <input class="form-check-input" type="radio" name="Booking_Type" value="3" id="guest">
                                <label class="form-check-label" for="guest">Guest</label>
                            </div>

                        </div>
                        <button id="forBradFormSubmit" class="btn" type="submit">Submit to Brad</button>
                    </div>
                </form>

Oooh, that is so close @Cheese!

If submitting without checking anything it does validate. However when you do select another option the first option stays red. So close!

Thank you!

Any reason not to use a radio over a check box?

:smiley:

Alternatively what about doing the validation on the server side rather than Client side? That way there is only the one input for the group to validate? :thinking:

Any reason not to use a radio over a check box?

Yeah, I need it to allow multiple options.

Alternatively what about doing the validation on the server side rather than Client side? That way there is only the one input for the group to validate?

Is there a way to show a validation message with server side validation?

What about a (required) hidden field linked to the checkbox group array?

    <form id="form1">

        <div class="form-group mb-3" id="input1_group" is="dmx-checkbox-group">

            <legend class="col-sm-2 col-form-label">Some checkboxes</legend>
            <div class="form-check">
                <input class="form-check-input" type="checkbox" value="1" id="input1_1" name="input1_1">
                <label class="form-check-label" for="input1_1">First checkbox</label>
            </div>
            <div class="form-check">
                <input class="form-check-input" type="checkbox" value="2" id="input1_2" name="input1_2">
                <label class="form-check-label" for="input1_2">Second checkbox</label>
            </div>
            <div class="form-check">
                <input class="form-check-input" type="checkbox" value="3" id="input1_3" name="input1_3">
                <label class="form-check-label" for="input1_3">Third checkbox</label>
            </div><input id="text1" name="text1" type="text" class="form-control visually-hidden" required="" dmx-bind:value="input1_group.value">
        </div><button id="btn1" class="btn" type="submit">Button</button>

    </form>

You’ll see something like:

image

But you can change that with css:


.was-validated .form-check-input:valid, .form-check-input.is-valid {
    border-color: #dee2e6;
}

.was-validated .form-check-input:valid~.form-check-label, .form-check-input.is-valid~.form-check-label {
    color: #212529;
}



image

2 Likes

OK got you, hmmmm…

I assume so as this is what happens if you use a Validation step in your Server Action, ie if an email address exists in the DB show ‘yada yada’ etc.

The hidden field with the CSS styling works perfect! Thank you both! I owe you guys a :beer:

2 Likes

So I ended up having to do a hybrid of both solutions. I had to have a hidden field with the selected values and use server side validation for validation (as @Cheese suggested) and submit the hidden field value to the data insert.

@franse method worked except for the case that if you submitted without selecting anything the validation would work, but then if you selected more than one option in the checkboxes it would only take the first checked value not all of them.

By combining the two solutions and getting a little creative I was able to achieve the desired results except for the CSS styling. The CSS that @franse provided only works for client side validation.

1 Like

Glad you got it working!

But I’m curious…

The form I posted above should return 1,2,3
Because it takes the values from the checkbox group array…

Sorry, not following :frowning_face: do you need to customize something else?

The form you posted works fantastic if submitted before an invalid submission. After an Invalid submission, for some reason it only accepts the value from the first one checked and the rest is ignored. No idea why.

As for the CSS, it turns red on invalid and remains red even after a valid choice was selected. For this use case, I can live with that. At least the selected choices turn green.

Thank you so much for your help. I have it working to a satisfactory level.

Would be great to have a built in Wappler way of required validation for Radio Buttons and CheckBoxes.

this what you want?

1 Like