Home > OS >  How to check if at least 2 checkboxes (in multiple groups) are selected within another if statement?
How to check if at least 2 checkboxes (in multiple groups) are selected within another if statement?

Time:12-09

I have this code which is working beautifully. It is just disabling a submit button if text input fields are empty.

$(document).ready(function() {
  $('input[required]').on('keyup', function() {
    var empty = false;
    
    $('input[required]').each(function() {
      var val = $(this).val().trim();
      
      if (val.length == 0 || typeof val == 'undefined') {
        empty = true;
      }
    })
    
    if (empty) {
      $('#register').css('opacity', '0.2').attr('disabled', 'disabled');
    } else {
      $('#register').css('opacity', '1').removeAttr('disabled');
    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<input type="text" required>
<input type="text" required>

<button type="button" id="register">register</button>

However, I also have multiple checkbox groups on the page. They have different group names.

How can I also include a check in this code to check that all groups of checkboxes have at least 2 checkboxes selected?

CodePudding user response:

You could use plain JS this.checked to check if the checkbox is checked and a simple counter:

var checked = 0;

if (this.checked) {
  checked  = 1;
}

Then you could instead of checking if (empty) {...}, check if (checked < 2) {...}.

Working example:

$(document).ready(function(){
    $('input[type=checkbox][required]').on('change', function() {
        var checked = 0;
        
        $('input[type=checkbox][required]').each(function(){
            if (this.checked) {
              checked  = 1;
            }
        });
        
        if (checked < 2) {
            $('#register').css('opacity', '0.2').attr('disabled', 'disabled');
        } else {
            $('#register').css('opacity', '1').removeAttr('disabled');
        }
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<input type="checkbox" name="test[]" required>
<input type="checkbox" name="test[]" required>

<button type="button" id="register">register</button>


If you also want to check this for multiple groups, you could first get all group names with an additional each() loop:

var groups = [];
            
$('input[type=checkbox][required]').each(function() {
  groups.push(this.name);
});

, filter out the duplicates:

groups = groups.filter( (x, i) => groups.indexOf(x) === i );

and then iterate over that group names, do the check like in the example above and count the checked groups:

var checked_groups = 0;

for (i = 0; i < groups.length; i  ) {
  ...
  if (checked > 1) {
    checked_groups  = 1;
  }
}

At the end you wouldn't check for the true var, but for:

if (checked_groups < groups.length) {...}

Working example:

$(document).ready(function() {
    $('input[type=checkbox][required]').on('change', function() {
        var groups = [];
        
        $('input[type=checkbox][required]').each(function() {
            groups.push(this.name);
        });
        
        groups = groups.filter( (x, i) => groups.indexOf(x) === i );
        var checked_groups = 0;
        
        for (i = 0; i < groups.length; i  ) {
          var checked = 0;
          
          $('input[type=checkbox][required][name="'   groups[i]   '"]').each(function() {
              if (this.checked) {
                checked  = 1;
              }
          });
          
          if (checked > 1) {
            checked_groups  = 1;
          }
        }
        
        if (checked_groups < groups.length) {
            $('#register').css('opacity', '0.2').attr('disabled', 'disabled');
        } else {
            $('#register').css('opacity', '1').removeAttr('disabled');
        }
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<input type="checkbox" name="test[]" required>
<input type="checkbox" name="test[]" required>
<input type="checkbox" name="foo[]" required>
<input type="checkbox" name="foo[]" required>

<button type="button" id="register">register</button>

CodePudding user response:

Since you are using jQuery you can leverage that - could also use plain JavaScript.

Here is a slight mix of both. I leverage data attributes both in the code and in the CSS to manage the "2" - but this could also be altered to use true checkboxes, radio buttons etc. You mentioned checkboxes but all your inputs are text so I went with your code vs descriptions.

Lots of comments in the code that can and should be removed for a final version.

$(function() {
  $('#register').on('set-allowed', function() {
    let inputGroups = $('.check-wrapper');
    let groupInputsWithValue = inputGroups.filter(function() {
      return $(this).data("has-entry") == 'yes';
    });
    let hasNoEntry = !(inputGroups.length == groupInputsWithValue.length || groupInputsWithValue > 1);
    //console.log("button:", hasNoEntry, inputGroups.length, groupInputsWithValue.length);
    // use prop not attr
    $(this).prop('disabled', hasNoEntry);
  });

  // use a change rather than a keyup to keep it less noisy
  $('input[required]').on('change', function() {
    let inputGroup = $(this).closest('.check-wrapper');
    let groupCount = inputGroup.find('input[required]').length;
    // now check all the inputs for a value
    let groupInputsWithValue = inputGroup.find('input[required]').filter(function() {
      let inputfield = $(this);
      let val = inputfield.val().trim();
      let notEmpty = val.length > 0;
      return notEmpty;
    });
    let showGood = groupInputsWithValue.length > 0;
    // we use attr here as .data() does show in the DOM and thus to CSS
    //inputGroup.attr('data-has-entry', showGood ? 'yes' : 'no');
    //native JavaScript dataset to do the same thing:
    inputGroup.get(0).dataset.hasEntry = showGood ? 'yes' : 'no';
    $('#register').trigger('set-allowed');
    //console.log(!!groupInputsWithValue.length, groupInputsWithValue.length);
  }).first().trigger("change");
});
.check-wrapper {
  border: solid #ffbbbb 1px;
  padding: 0.5rem;
  background-color: #ffdddd;
}

.check-wrapper[data-has-entry='yes'] {
  border: solid green 1px;
  background-color: #ddffdd;
}

#register {
  background-color: #ddffdd;
  cursor: not-allowed;
  border: solid #d1d1d1 1px;
  cursor: crosshair;
  opacity: 1;
}

#register:disabled {
  background-color: #ffaaaa;
  color: #000000;
  cursor: not-allowed;
  border: solid #ff0000 1px;
  opacity: 0.2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
  <input type="text" required>
  <input type="text" required>
</div>
<div >
  <input type="text" required>
  <input type="text" required>
</div>
<div >
  <input type="text" required>
  <input type="text" required> <input type="text" required>
</div>
<div >
  <input type="text" required>
  <input type="text" required>
</div>
<button type="button" id="register">register</button>

  • Related