3

I have two check boxes in my form, all other form fields use HTML attribute required so I can run validation on submit. This is little different since I have two check box input fields and I have to require at least one to be checked. Here is an example:

$('.frm-Submit').on('submit', submitFrm);
function submitFrm(e){
    e.preventDefault(); // Prevnts default form submit.
    var $checkbox = $('.account-type');

    $checkbox.on('change', function(){
        var checked = false;
  
        $checkbox.each(function(){
           checked = checked || $(this).is(':checked')
        });
  
        $checkbox.prop('required', !checked)
    });

    console.log('Submit form.')
}
.form-group.required .control-label:after {
    content: " *";
    color: red;
}
<script language="javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script language="javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

<form name="frmSave" id="frmSave" class="frm-Submit" autocomplete="off">
  <div class="form-group required">
    <label class="control-label" for="account"><span class="label label-primary">Account Type:</span></label>
    <div class="checkbox">
      <label for="user">
         <input type="checkbox" name="frm_isuser" id="frm_isuser" data-toggle="collapse" data-target="#user-account" required class="account-type"> <span class="label label-default">User</span>
      </label>
      <label for="staff">
         <input type="checkbox" name="frm_isstaff" id="frm_isstaff" data-toggle="collapse" data-target="#staff-account" required class="account-type"> <span class="label label-info">Staff</span>
      </label>
    </div>
  </div>
   <div class="row">
     <div class="form-group col-xs-12 col-sm-12 col-md-1 col-lg-1">
       <button type="submit" name="frm_submit" id="frm_submit" class="btn btn-primary">Submit</button>
     </div>
   </div> 
</form>

Example above throws an error isUser.checkValidity() is not a function. Is there a way to run validity on checkbox and make at least one of the two required/checked?

TylerH
  • 20,799
  • 66
  • 75
  • 101
espresso_coffee
  • 5,980
  • 11
  • 83
  • 193

3 Answers3

5

$("#frm_isuser").is(":checked") will return a bool that shows if $("#frm_isuser") is checked or not.

And checkValidity() is a DOM methods, so you should use document.getElementById("frm_isuser").checkValidity() or $("#frm_isuser")[0].checkValidity().

Edit: If one of the both checkboxes is checked, then set required attributes to false to both of them. If none of them is checked, set required to true.

$('.frm-Submit').on('submit', submitFrm);

var $checkbox = $('.custom-class')

$checkbox.on('change', function(){
  var checked = false;
  
  $checkbox.each(function(){
    checked = checked || $(this).is(':checked')
  })
  
  $checkbox.prop('required', !checked)
})

function submitFrm(e) {
  e.preventDefault(); // Prevnts default form submit.
  
  console.log('Submit form.')
}
.form-group.required .control-label:after {
  content: " *";
  color: red;
}
<script language="javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script language="javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

<form name="frmSave" id="frmSave" class="frm-Submit" autocomplete="off">
  <div class="form-group required">
    <label class="control-label" for="account"><span class="label label-primary">Account Type:</span></label>
    <div class="checkbox">
      <label for="user">
         <input type="checkbox" name="frm_isuser" id="frm_isuser" data-toggle="collapse" data-target="#user-account" required class="custom-class"> <span class="label label-default">User</span>
      </label>
      <label for="staff">
         <input type="checkbox" name="frm_isstaff" id="frm_isstaff" data-toggle="collapse" data-target="#staff-account" required class="custom-class"> <span class="label label-info">Staff</span>
      </label>
    </div>
  </div>
  <div class="row">
    <div class="form-group col-xs-12 col-sm-12 col-md-1 col-lg-1">
      <button type="submit" name="frm_submit" id="frm_submit" class="btn btn-primary">Submit</button>
    </div>
  </div>
</form>
Hikarunomemory
  • 4,237
  • 2
  • 11
  • 21
  • I do not see HTML5 validation message if I click submit and both check boxes are unchecked. – espresso_coffee Apr 23 '18 at 15:48
  • Cause you didn't add `required` attribute to the checkboxes. Now I update the snippet. – Hikarunomemory Apr 23 '18 at 15:50
  • Again, I do not want to require both of them, I only need one at least to be checked. So either User or Staff has to be checked. – espresso_coffee Apr 23 '18 at 15:51
  • Please check my snippet above, I have used the same code but still both check boxes are required. – espresso_coffee Apr 23 '18 at 16:25
  • You forgot to replace `$('.custom-class')` with `$('.account-type')` – Hikarunomemory Apr 23 '18 at 16:27
  • I have changed the class and still the same. – espresso_coffee Apr 23 '18 at 16:28
  • 1
    You have to take the change event outside the `submitFrm` function, or it will check if is required first. So take out the change event and it would be triggered when checked or unchecked the checkboxes. – Hikarunomemory Apr 23 '18 at 16:35
  • I have one more question. So if only User check box is checked then I will show form fields for user account. Staff form fields will be hidden. When I populate all required fields for user I still can't submit the form because hidden fields that are required have to bee filled in. How to prevent those hidden fields to be included in validation? – espresso_coffee Apr 23 '18 at 17:37
  • Also I do not think that you need this `checked = checked || $(this).is(':checked')` that can be replaced with `checked = $(this).is(':checked')` – espresso_coffee Apr 23 '18 at 18:11
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/169627/discussion-between-hikarunomemory-and-espresso-coffee). – Hikarunomemory Apr 23 '18 at 22:39
  • I implemented this solution and got it to work, but would like to configure the alert so that it doesn't point to the first of the two checkboxes. – user3120861 Nov 24 '19 at 20:13
  • This hack works well. I was hoping to overwrite each checkbox's `checkValidity()` function, but the browser disregards it. I also tried to modify directly the `el.validity.valid` value but since it is "live" it won't take the value. – Guillaume Bois Aug 24 '23 at 14:21
2

add like this,

$(function(){
 
 $('[type="checkbox"]').prop('required', true);
 $('[type="checkbox"]').filter('[required]').change(function(){
  $('[type="checkbox"]').prop('required', ($(this).is(':checked')) ? false : true);
 })
 $('.frm-Submit').on('submit', function(e){
        e.preventDefault(); // Prevnts default form submit.  
        if($('[type="checkbox"]:checked').length > 0){   
            console.log('Submit form.')
        }else{
   $(this).closest('form').get(0).checkValidity();
  }
    });
 
});
<script language="javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script language="javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

<form name="frmSave" id="frmSave" class="frm-Submit" autocomplete="off">
  <div class="form-group required">
    <label class="control-label" for="account"><span class="label label-primary">Account Type:</span></label>
    <div class="checkbox">
      <label for="user">
         <input type="checkbox" name="frm_isuser" id="frm_isuser" data-toggle="collapse" data-target="#user-account"> <span class="label label-default">User</span>
      </label>
      <label for="staff">
         <input type="checkbox" name="frm_isstaff" id="frm_isstaff" data-toggle="collapse" data-target="#staff-account"> <span class="label label-info">Staff</span>
      </label>
    </div>
  </div>
   <div class="row">
     <div class="form-group col-xs-12 col-sm-12 col-md-1 col-lg-1">
       <button type="submit" name="frm_submit" id="frm_submit" class="btn btn-primary">Submit</button>
     </div>
   </div> 
</form>
Anfath Hifans
  • 1,588
  • 1
  • 11
  • 20
1

.is(":checked") already returns a boolean...there is no .checkValidity() method. Just do:

if (isUser || isStaff) {
  //...code here if at least one is true
}

Update:

The requirement and validation that you need in this case are essentially two separate sets of logic.

Constraint validation runs on a per input basis so you have to check multiple inputs yourself.

You have the option of swapping the value of the required parameter by listening for events on each checkbox...but since they seem to have different data-target, I assume the better solution would probably be just using the select form type.

ReyHaynes
  • 2,932
  • 1
  • 15
  • 22
  • I would like to show HTML5 validation message if neither of check boxes are checked. – espresso_coffee Apr 23 '18 at 15:47
  • Updated my response with more of an explanation on how `checkValidity` works but you can check @Hikarunomemory answer on how swapping `required` can get you your desired result. – ReyHaynes Apr 23 '18 at 16:30