web-dev-qa-db-fra.com

Attribut requis sur plusieurs cases du même nom?

J'ai une liste de cases à cocher avec le même attribut de nom, et je dois valider qu'au moins l'une d'entre elles a été sélectionnée. 

Mais lorsque j'utilise l'attribut html5 "requis" sur chacun d'entre eux, le navigateur (chrome & ff) ne me permet pas de soumettre le formulaire à moins que tous ne soient cochés.

exemple de 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 />

Lorsque vous utilisez la même chose avec des entrées radio, le formulaire fonctionne comme prévu (si l'une des options est sélectionnée, le formulaire est validé)

Selon Joe Hopfgartner (qui prétend citer les spécifications html5), le comportement supposé est le suivant

Pour les cases à cocher, l'attribut requis ne sera satisfait que si une ou plusieurs des cases à cocher portant ce nom sous cette forme sont cochées.

Pour les boutons radio, l'attribut requis ne doit être satisfait que lorsque l'un des boutons radio de ce groupe de radio est coché.

est-ce que je fais quelque chose de mal, ou est-ce un bug de navigateur (sur les deux chrome et ff)?

26
anna.mi

Désolé, maintenant que j'ai lu ce que vous espériez mieux, j'actualise la réponse.

Sur la base des Spécifications HTML5 du W3C, rien n’est faux. J'ai créé ce test JSFiddle et il se comporte correctement en fonction des spécifications (pour les navigateurs basés sur les spécifications, comme Chrome 11 et 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>

Je conviens que ce n'est pas très utilisable (en fait, beaucoup de gens se sont plaints à ce sujet dans les listes de diffusion du du W3C ).

Mais les navigateurs ne font que suivre les recommandations de la norme, ce qui est correct. La norme est un peu trompeuse, mais nous ne pouvons rien y faire en pratique. Vous pouvez toujours utiliser JavaScript pour la validation de formulaire, bien que, comme un bon plugin de validation jQuery.

Une autre approche consisterait à choisir un polyfill qui peut permettre à (presque) tous les navigateurs d’interpréter correctement la validation de formulaire.

16

Vous pouvez le faire avec jQuery moins de lignes:

$(function(){

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

    requiredCheckboxes.change(function(){

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

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

});

Avec$ (': case à cocher [requis]')vous sélectionnez toutes les cases à cocher avec l'attribut required, puis avec la méthode .change appliquée à ce groupe de cases à cocher vous pouvez exécuter la fonction de votre choix lorsqu'un élément de ce groupe change. Dans ce cas, si l'une des cases à cocher est cochée, je supprime l'attribut required pour toutes les cases à cocher du groupe sélectionné.

J'espère que ça aide.

Adieu.

24
vantesllar

j'ai eu le même problème, ma solution a été d'appliquer l'attribut requis à tous les éléments

<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>

lorsque l'utilisateur coche l'un des éléments, je supprime l'attribut requis de tous les éléments:

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');
    }

 });
5
Rommel Castro

Voici une amélioration pour la réponse d'icova. Il regroupe également les entrées par nom.

$(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');
        }
      });
    }();
  }

});
4
Zhomart

Pour fournir une autre approche similaire à la réponse de @IvanCollantes ..__, cela fonctionne en filtrant en plus les cases à cocher requises par nom. J'ai aussi un peu simplifié le code.

jQuery(document).ready(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);
  });
});
<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" 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>

2
fyrye

Un petit correctif jQuery:

$(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');
        }
    });
});
1
Yukulélé

Sur la base de la réponse d’icova, voici le code qui vous permet d’utiliser un message de validation HTML5 personnalisé:

$(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('');});
    });
});
0
OMA
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
Marcos Alberton