skip to Main Content

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?

2

Answers


  1. 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>
    Login or Signup to reply.
  2. 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 class="check-wrapper">
      <input type="text" required>
      <input type="text" required>
    </div>
    <div class="check-wrapper">
      <input type="text" required>
      <input type="text" required>
    </div>
    <div class="check-wrapper">
      <input type="text" required>
      <input type="text" required> <input type="text" required>
    </div>
    <div class="check-wrapper">
      <input type="text" required>
      <input type="text" required>
    </div>
    <button type="button" id="register">register</button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search