Les entrées de case à cocher ne publient-elles les données que si elles sont cochées?

184

Est-ce un comportement standard pour les navigateurs d'envoyer uniquement les données de valeur d'entrée de case à cocher si elle est cochée lors de la soumission du formulaire?

Et si aucune donnée de valeur n'est fournie, la valeur par défaut est-elle toujours "on"?

En supposant que ce qui précède est correct, ce comportement est-il cohérent dans tous les navigateurs?

marque
la source

Réponses:

187

Oui, le comportement standard est que la valeur n'est envoyée que si la case est cochée. Cela signifie généralement que vous devez avoir un moyen de vous souvenir des cases à cocher que vous attendez du côté serveur, car toutes les données ne reviennent pas du formulaire.

La valeur par défaut est toujours «on», cela doit être cohérent entre les navigateurs.

Ceci est couvert dans la recommandation HTML 4 du W3C :

Les cases à cocher (et les boutons radio) sont des interrupteurs marche / arrêt qui peuvent être basculés par l'utilisateur. Un commutateur est "activé" lorsque l'attribut vérifié de l'élément de contrôle est défini. Lorsqu'un formulaire est soumis, seuls les contrôles de case à cocher «on» peuvent réussir.

Jean C
la source
18
Malheureusement, c'est douloureux, seules les cases à cocher cochées sont envoyées au serveur, pas celles qui ne le sont pas. Si vous savez à l'avance quelles cases à cocher se trouvent sur la page, ce n'est pas un problème sur le script côté serveur de les gérer. Le problème est lorsque vous ne savez pas cela à l'avance - des cases à cocher créées dynamiquement sur la page en fonction d'une logique métier. Ensuite, vous devez faire des astuces et utiliser des champs de saisie masqués parallèles pour ces cases à cocher et les remplir avec JavaScript.
sbrbot
La clé pour créer un validateur cohérent avec "les contrôles infructueux autorisés (par exemple, type =" case à cocher ") est de désigner ces contrôles de formulaire comme transitoires . Lorsqu'ils ne réussissent pas, modifiez dynamiquement votre désinfectant et votre validateur en conséquence.
Anthony Rutledge
3
Solution de contournement: utiliser <select>avec deux options onet off:-)
andy
83

En HTML, chaque <input />élément est associé à une paire nom / valeur unique (mais pas unique). Cette paire est envoyée dans la requête suivante (dans ce cas, un corps de requête POST) uniquement si le <input />est "réussi".

Donc, si vous avez ces entrées dans votre <form>DOM:

<input type="text"     name="one"   value="foo"                        />
<input type="text"     name="two"   value="bar"    disabled="disabled" />
<input type="text"     name="three" value="first"                      />
<input type="text"     name="three" value="second"                     />

<input type="checkbox" name="four"  value="baz"                        />
<input type="checkbox" name="five"  value="baz"    checked="checked"   />
<input type="checkbox" name="six"   value="qux"    checked="checked" disabled="disabled" />
<input type="checkbox" name=""      value="seven"  checked="checked"   />

<input type="radio"    name="eight" value="corge"                      />
<input type="radio"    name="eight" value="grault" checked="checked"   />
<input type="radio"    name="eight" value="garply"                     />

Générera ces paires nom + valeur qui seront soumises au serveur:

one=foo
three=first
three=second
five=baz
eight=grault

Remarquerez que:

  • twoet sixont été exclus parce qu'ils avaient l' disabledensemble d'attributs.
  • three a été envoyé deux fois car il contenait deux entrées valides portant le même nom.
  • fourn'a pas été envoyé car c'est un checkboxqui n'a pas étéchecked
  • sixn'a pas été envoyé malgré le fait checkedque l' disabledattribut a une priorité plus élevée.
  • sevenn'a pas d' name=""attribut envoyé, il n'est donc pas soumis.

En ce qui concerne votre question: vous pouvez voir qu'une case à cocher non cochée n'aura donc pas sa paire nom + valeur envoyée au serveur - mais d'autres entrées partageant le même nom seront envoyées avec lui.

Des cadres comme ASP.NET MVC contournent ce problème en associant (subrepticement) chaque checkboxentrée à une hiddenentrée dans le HTML rendu, comme ceci:

@Html.CheckBoxFor( m => m.SomeBooleanProperty )

Rendus:

<input type="checkbox" name="SomeBooleanProperty" value="true" />
<input type="hidden"   name="SomeBooleanProperty" value="false" />

Si l'utilisateur ne coche pas la case, les informations suivantes seront envoyées au serveur:

SomeBooleanProperty=false

Si l'utilisateur coche la case, les deux seront envoyés:

SomeBooleanProperty=true
SomeBooleanProperty=false

Mais le serveur ignorera la =falseversion car il voit la =trueversion, et donc s'il ne la voit pas, =trueil peut déterminer que la case à cocher a été rendue et que l'utilisateur ne l'a pas cochée - par opposition à ce que les SomeBooleanPropertyentrées ne soient pas rendues du tout.

Dai
la source
Il convient de noter que si vous avez plusieurs champs, comme avec la zone de texte cachée supplémentaire, le backend recevra un tableau de valeurs.
Salami
Il ne reçoit un tableau que si vous utilisez []à la fin du nom d'entrée, le comportement par défaut est de soumettre uniquement le dernier élément avec ce nom, donc tant que l'entrée masquée est avant la case à cocher, cela fonctionnera.
beeglebug
En ayant deux champs avec le même nom (champ caché + champ de case à cocher), et en cochant la case, la valeur de publication est une chaîne séparée par des virgules des valeurs, c'est-à-dire. quelque chose comme "0,1"
ʞᴉɯ
1
@beeglebug Ce que vous décrivez, c'est comment PHP gère les noms et les valeurs, le []suffixe ne fait pas partie de la spécification HTML et les navigateurs ne le traitent pas spécialement. Sans le []PHP ne permettra l'accès qu'à une seule valeur (la dernière valeur) au lieu de toutes les valeurs.
Dai
1
Utiliser la propriété hidden avant que la case à cocher ne fonctionne pour moi dans tous les navigateurs que j'ai testés en utilisant GET et POST avec PHP. Lorsque je l'ai placé après le contrôle de la case à cocher, le résultat était toujours faux.
adrianwadey
16

Si la case n'est pas cochée, cela ne contribue pas aux données envoyées lors de la soumission du formulaire.

La section HTML5 4.10.22.4 Construction de l'ensemble de données de formulaire décrit la façon dont les données de formulaire sont construites:

Si l'une des conditions suivantes est remplie, ignorez ces sous-étapes pour cet élément: [...]

L'élément field est un élément d'entrée dont l'attribut type est dans l'état Case à cocher et dont la vérification est fausse.

puis la valeur par défaut onest spécifiée si elle valueest manquante:

Sinon, si l'élément de champ est un élément d'entrée dont l'attribut type est dans l'état Case à cocher ou dans l'état Bouton radio, exécutez ces sous-étapes imbriquées supplémentaires:

Si l'élément de champ a un attribut de valeur spécifié, laissez value être la valeur de cet attribut; sinon, laissez value la chaîne "on".

Ainsi, les cases à cocher non cochées sont ignorées lors de la construction des données de formulaire.

Un comportement similaire est requis sous HTML4 . Il est raisonnable d'attendre ce comportement de la part de tous les navigateurs compatibles.

Adam Zalcman
la source
10

Les cases à cocher affichent la valeur «on» si et seulement si la case est cochée. Insted of catching checkbox value, vous pouvez utiliser des entrées cachées

JS :

var chk = $('input[type="checkbox"]');
    chk.each(function(){
        var v = $(this).attr('checked') == 'checked'?1:0;
        $(this).after('<input type="hidden" name="'+$(this).attr('rel')+'" value="'+v+'" />');
    });

chk.change(function(){ 
        var v = $(this).is(':checked')?1:0;
        $(this).next('input[type="hidden"]').val(v);
    });

HTML :

<label>Active</label><input rel="active" type="checkbox" />
Lanister
la source
8

Est-ce un comportement standard pour les navigateurs d'envoyer uniquement les données de valeur d'entrée de case à cocher si elle est cochée lors de la soumission du formulaire?

Oui, car sinon, il n'y aurait pas de moyen solide de déterminer si la case à cocher a réellement été cochée ou non (si elle modifiait la valeur, le cas peut exister lorsque la valeur souhaitée si elle était cochée serait la même que celle qu'elle était remplacé par).

Et si aucune donnée de valeur n'est fournie, la valeur par défaut est-elle toujours "on"?

D'autres réponses confirment que "on" est la valeur par défaut. Cependant, si la valeur ne vous intéresse pas, utilisez simplement:

if (isset($_POST['the_checkbox'])){
    // name="the_checkbox" is checked
}
Geai
la source
7

De la spécification HTML 4, qui devrait être cohérente dans presque tous les navigateurs:

http://www.w3.org/TR/html401/interact/forms.html#checkbox

Les cases à cocher (et les boutons radio) sont des interrupteurs marche / arrêt qui peuvent être basculés par l'utilisateur. Un commutateur est "activé" lorsque l'attribut vérifié de l'élément de contrôle est défini. Lorsqu'un formulaire est soumis, seuls les contrôles de case à cocher «on» peuvent réussir.

La réussite est définie comme suit:

Un contrôle réussi est «valide» pour la soumission. Chaque contrôle réussi a son nom de contrôle associé à sa valeur actuelle dans le cadre de l'ensemble de données de formulaire soumis. Un contrôle réussi doit être défini dans un élément FORM et doit avoir un nom de contrôle.

Alex W
la source
5

input type = "hidden" name = "is_main" value = "0"

input type = "checkbox" name = "is_main" value = "1"

afin que vous puissiez contrôler comme ça comme je l'ai fait dans l'application. s'il vérifie alors envoyer la valeur 1 sinon 0

Muhammad Amir Shahzad
la source
3

Aucune des réponses ci-dessus ne m'a satisfait. J'ai trouvé que la meilleure solution est d'inclure une entrée masquée avant chaque entrée de case à cocher avec le même nom.

<input type="hidden" name="foo[]" value="off"/>

<input type="checkbox" name="foo[]"/>

Ensuite, du côté du serveur, en utilisant un petit algorithme, vous pouvez obtenir quelque chose de plus que HTML devrait fournir.

function checkboxHack(array $checkbox_input): array
{
    $foo = [];
    foreach($checkbox_input as $value) {
        if($value === 'on') {
            array_pop($foo);
        }
        $foo[] = $value;
    }
    return $foo;
}

Ce sera l'entrée brute

array (
    0 => 'off',
    1 => 'on',
    2 => 'off',
    3 => 'off',
    4 => 'on',
    5 => 'off',
    6 => 'on',
),

Et la fonction retournera

array (
    0 => 'on',
    1 => 'off',
    2 => 'on',
    3 => 'on',
)  
Cobolt
la source
1

J'ai une page (formulaire) qui génère dynamiquement une case à cocher, donc ces réponses ont été d'une grande aide. Ma solution est très similaire à beaucoup ici mais je ne peux m'empêcher de penser qu'elle est plus facile à mettre en œuvre.

J'ai d'abord mis une zone de saisie cachée en ligne avec ma case à cocher, c'est-à-dire

 <td><input class = "chkhide" type="hidden" name="delete_milestone[]" value="off"/><input type="checkbox" name="delete_milestone[]"   class="chk_milestone" ></td>

Désormais, si tous les checkboxessont désélectionnés, les valeurs renvoyées par le champ masqué seront toutes désactivées.

Par exemple, ici avec cinq cases à cocher insérées dynamiquement, la forme POSTSdes valeurs suivantes:

  'delete_milestone' => 
array (size=7)
  0 => string 'off' (length=3)
  1 => string 'off' (length=3)
  2 => string 'off' (length=3)
  3 => string 'on' (length=2)
  4 => string 'off' (length=3)
  5 => string 'on' (length=2)
  6 => string 'off' (length=3)

Cela montre que seules les 3e et 4e cases à cocher sont onou checked.

En substance, le champ d'entrée factice ou masqué indique simplement que tout est désactivé à moins qu'il n'y ait un "on" sous l'index off, qui vous donne alors l'index dont vous avez besoin sans une seule ligne de code côté client.

.

Alexandre
la source
0

Tout comme la variante ASP.NET, sauf mettre l'entrée masquée avec le même nom avant la case à cocher réelle (du même nom). Seules les dernières valeurs seront envoyées. De cette façon, si une case est cochée, son nom et sa valeur "on" sont envoyés, alors que si elle n'est pas cochée, le nom de l'entrée masquée correspondante et la valeur que vous aimeriez lui donner seront envoyés. À la fin, vous obtiendrez le tableau $ _POST à ​​lire, avec tous les éléments cochés et non cochés, les valeurs "on" et "false", pas de clés en double. Facile à traiter en PHP.

user3124825
la source
0

Ayant le même problème avec les cases à cocher non cochées qui ne seront pas envoyées lors de l'envoi de formulaires, j'ai proposé une autre solution que de refléter les éléments de la case à cocher.

Obtenir toutes les cases à cocher non cochées avec

var checkboxQueryString;

$form.find ("input[type=\"checkbox\"]:not( \":checked\")" ).each(function( i, e ) {
  checkboxQueryString += "&" + $( e ).attr( "name" ) + "=N"
});
Maugo
la source
-2

J'ai résolu le problème avec ce code:

Formulaire HTML

<input type="checkbox" id="is-business" name="is-business" value="off" onclick="changeValueCheckbox(this)" >
<label for="is-business">Soy empresa</label>

et la fonction javascript en modifiant la forme de la valeur de la case à cocher:

//change value of checkbox element
function changeValueCheckbox(element){
   if(element.checked){
    element.value='on';
  }else{
    element.value='off';
  }
}

et le serveur a vérifié si la publication de données est «activée» ou «désactivée». J'ai utilisé playframework java

        final Map<String, String[]> data = request().body().asFormUrlEncoded();

        if (data.get("is-business")[0].equals('on')) {
            login.setType(new MasterValue(Login.BUSINESS_TYPE));
        } else {
            login.setType(new MasterValue(Login.USER_TYPE));
        }
Yonatan Alexis Quintero Rodrig
la source