开发者

Required attribute on multiple checkboxes with the same name? [duplicate]

This question already has answers here: Using the HTML5 "required" attribute for a group of checkboxes? (16 answers) Closed 6 years ago.

I have a list of checkboxes with the same name attribute, and I need to validate that at least one of them has been selected.

But when I use the html5 attribute "required" on all of them, the browser (chrome & ff) doesn't allow me to submit the form unless all of them are checked.

sample code:

<label for="a-0">a-0</label>
<input type="checkbox" name="q-8" id="a-0" required />
<label for="a-1">a-1</label>
<input type="checkbox" name="q-8" id="a-1" required />
<label for="a-2">a-2</label>
<input type="checkbox" name="q-8" id="a-2" required />

When using the same with radio inputs, the form works as expected (if one of the options is selected the form validates)

According to Joe Hopfgartner (who claims to quote the html5 specs), the supposed behaviour is:

For checkboxes, the required attribute shall only be satisfied when one or more of the checkboxes with that name in that form are checked.

For radio buttons, the required attribute shall only be satisfied when exactly one of the radio buttons in that radio group is checked.

am i doing something wrong, or is this a brow开发者_如何学编程ser bug (on both chrome & ff) ??


You can make it with jQuery a less lines:

$(function(){

    var requiredCheckboxes = $(':checkbox[required]');

    requiredCheckboxes.change(function(){

        if(requiredCheckboxes.is(':checked')) {
            requiredCheckboxes.removeAttr('required');
        }

        else {
            requiredCheckboxes.attr('required', 'required');
        }
    });

});

With $(':checkbox[required]') you select all checkboxes with the attribute required, then, with the .change method applied to this group of checkboxes, you can execute the function you want when any item of this group changes. In this case, if any of the checkboxes is checked, I remove the required attribute for all of the checkboxes that are part of the selected group.

I hope this helps.

Farewell.


Sorry, now I've read what you expected better, so I'm updating the answer.

Based on the HTML5 Specs from W3C, nothing is wrong. I created this JSFiddle test and it's behaving correctly based on the specs (for those browsers based on the specs, like Chrome 11 and Firefox 4):

<form>
    <input type="checkbox" name="q" id="a-0" required autofocus>
    <label for="a-0">a-1</label>
    <br>

    <input type="checkbox" name="q" id="a-1" required>
    <label for="a-1">a-2</label>
    <br>

    <input type="checkbox" name="q" id="a-2" required>
    <label for="a-2">a-3</label>
    <br>

    <input type="submit">
</form>

I agree that it isn't very usable (in fact many people have complained about it in the W3C's mailing lists).

But browsers are just following the standard's recommendations, which is correct. The standard is a little misleading, but we can't do anything about it in practice. You can always use JavaScript for form validation, though, like some great jQuery validation plugin.

Another approach would be choosing a polyfill that can make (almost) all browsers interpret form validation rightly.


To provide another approach similar to the answer by @IvanCollantes. It works by additionally filtering the required checkboxes by name. I also simplified the code a bit and checks for a default checked checkbox.

jQuery(function($) {
  var requiredCheckboxes = $(':checkbox[required]');
  requiredCheckboxes.on('change', function(e) {
    var checkboxGroup = requiredCheckboxes.filter('[name="' + $(this).attr('name') + '"]');
    var isChecked = checkboxGroup.is(':checked');
    checkboxGroup.prop('required', !isChecked);
  });
  requiredCheckboxes.trigger('change');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form target="_blank">
  <p>
    At least one checkbox from each group is required...
  </p>
  <fieldset>
    <legend>Checkboxes Group test</legend>
    <label>
      <input type="checkbox" name="test[]" value="1" checked="checked" required="required">test-1
    </label>
    <label>
      <input type="checkbox" name="test[]" value="2" required="required">test-2
    </label>
    <label>
      <input type="checkbox" name="test[]" value="3" required="required">test-3
    </label>
  </fieldset>
  <br>
  <fieldset>
    <legend>Checkboxes Group test2</legend>
    <label>
      <input type="checkbox" name="test2[]" value="1" required="required">test2-1
    </label>
    <label>
      <input type="checkbox" name="test2[]" value="2" required="required">test2-2
    </label>
    <label>
      <input type="checkbox" name="test2[]" value="3" required="required">test2-3
    </label>
  </fieldset>
  <hr>
  <button type="submit" value="submit">Submit</button>
</form>


i had the same problem, my solution was apply the required attribute to all elements

<input type="checkbox" name="checkin_days[]" required="required" value="0" /><span class="w">S</span>
<input type="checkbox" name="checkin_days[]" required="required" value="1" /><span class="w">M</span>
<input type="checkbox" name="checkin_days[]" required="required" value="2" /><span class="w">T</span>
<input type="checkbox" name="checkin_days[]" required="required" value="3" /><span class="w">W</span>
<input type="checkbox" name="checkin_days[]" required="required" value="4" /><span class="w">T</span>
<input type="checkbox" name="checkin_days[]" required="required" value="5" /><span class="w">F</span>
<input type="checkbox" name="checkin_days[]" required="required" value="6" /><span class="w">S</span>

when the user check one of the elements i remove the required attribute from all elements:

var $checkedCheckboxes = $('#recurrent_checkin :checkbox[name="checkin_days[]"]:checked'),
    $checkboxes = $('#recurrent_checkin :checkbox[name="checkin_days[]"]');

$checkboxes.click(function() {

if($checkedCheckboxes.length) {
        $checkboxes.removeAttr('required');
    } else {
        $checkboxes.attr('required', 'required');
    }

 });


Here is improvement for icova's answer. It also groups inputs by name.

$(function(){
  var allRequiredCheckboxes = $(':checkbox[required]');
  var checkboxNames = [];

  for (var i = 0; i < allRequiredCheckboxes.length; ++i){
    var name = allRequiredCheckboxes[i].name;
    checkboxNames.push(name);
  }

  checkboxNames = checkboxNames.reduce(function(p, c) {
    if (p.indexOf(c) < 0) p.push(c);
    return p;
  }, []);

  for (var i in checkboxNames){
    !function(){
      var name = checkboxNames[i];
      var checkboxes = $('input[name="' + name + '"]');
      checkboxes.change(function(){
        if(checkboxes.is(':checked')) {
          checkboxes.removeAttr('required');
        } else {
          checkboxes.attr('required', 'required');
        }
      });
    }();
  }

});


A little jQuery fix:

$(function(){
    var chbxs = $(':checkbox[required]');
    var namedChbxs = {};
    chbxs.each(function(){
        var name = $(this).attr('name');
        namedChbxs[name] = (namedChbxs[name] || $()).add(this);
    });
    chbxs.change(function(){
        var name = $(this).attr('name');
        var cbx = namedChbxs[name];
        if(cbx.filter(':checked').length>0){
            cbx.removeAttr('required');
        }else{
            cbx.attr('required','required');
        }
    });
});


Building on icova's answer, here's the code so you can use a custom HTML5 validation message:

$(function() {
    var requiredCheckboxes = $(':checkbox[required]');
    requiredCheckboxes.change(function() {
        if (requiredCheckboxes.is(':checked')) {requiredCheckboxes.removeAttr('required');}
        else {requiredCheckboxes.attr('required', 'required');}
    });
    $("input").each(function() {
        $(this).on('invalid', function(e) {
            e.target.setCustomValidity('');
            if (!e.target.validity.valid) {
                e.target.setCustomValidity('Please, select at least one of these options');
            }
        }).on('input, click', function(e) {e.target.setCustomValidity('');});
    });
});


var verifyPaymentType = function () {
   //coloque os checkbox dentro de uma div com a class checkbox
  var inputs =  window.jQuery('.checkbox').find('input');
  var first = inputs.first()[0];

  inputs.on('change', function () {
    this.setCustomValidity('');
  });

  first.setCustomValidity( window.jQuery('.checkbox').find('input:checked').length === 0 ? 'Choose one' : '');
}

window.jQuery('#submit').click(verifyPaymentType);

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜