Comment définir l'attribut HTML5 obligatoire en Javascript?

89

J'essaie de marquer une zone de textsaisie comme requis dans Javascript.

<input id="edName" type="text" id="name">

Si le champ est initialement marqué comme required:

<form>
    <input id="edName" type="text" id="name" required><br>
    <input type="submit" value="Search">
</form>

lorsque l'utilisateur essaie de soumettre une erreur de validation:

entrez la description de l'image ici

Mais maintenant je veux définir l' requiredattribut à "runtime" , via Javascript:

<form>
    <input id="edName" type="text" id="name"><br>
    <input type="submit" value="Search">
</form>

avec le script correspondant:

//recommended W3C HTML5 syntax for boolean attributes
document.getElementById("edName").attributes["required"] = "";         

Sauf lorsque je soumets maintenant, il n'y a pas de contrôle de validation, pas de blocage.

Quelle est la bonne façon de définir un attribut booléen de validation HTML5 ?

jsFiddle

Quelle est la valeur de l'attribut, demandez-vous?

L' requiredattribut de validation HTML5 est documenté comme Boolean:

4.10.7.3.4 L' requiredattribut

L' requiredattribut est un attribut booléen . Lorsqu'il est spécifié, l'élément est obligatoire.

Il y a beaucoup de discussions sur la manière de définir un booleanattribut. La spécification HTML5 note:

La présence d'un attribut booléen sur un élément représente la valeur vraie et l'absence de l'attribut représente la valeur fausse.

Si l'attribut est présent, sa valeur doit être la chaîne vide ou une valeur qui correspond à une correspondance ASCII insensible à la casse pour le nom canonique de l'attribut, sans espace de début ou de fin.

Cela signifie que vous pouvez spécifier un attribut required booléen de deux manières différentes:

edName.attributes.required = ""; //the empty string
edName.attributes.required = "required"; //the attribute's canonical name

Mais quelle est vraiment la valeur de l'attribut ?

Lorsque vous regardez mon jsFiddle de ce problème , vous remarquerez que si l' requiredattribut est défini dans le balisage:

<input id="edName" type="text" id="name" required>

Alors la valeur de l'attribut n'est pas la chaîne vide, ni le nom canonique de l'attribut:

edName.attributes.required = [object Attr]

Cela pourrait conduire à une solution.

Ian Boyd
la source
4
Je ne comprends pas pourquoi ils ne le permettent pas required="false", ont-ils déjà écrit un modèle avant d'écrire la norme? Les attributs conditionnels sont généralement pénibles, il est beaucoup plus facile de simplement mettre ce booléen dans la valeur d'attribut ...
Christophe Roussy
Est-il possible d'afficher manuellement ce texte sur l'entrée requise: "Veuillez remplir ce champ."?
zygimantus

Réponses:

116

requiredest une propriété réfléchie (comme id, name, type, et autres), de sorte que :

element.required = true;

... où elementest l' inputélément DOM réel , par exemple:

document.getElementById("edName").required = true;

(Juste pour être complet.)

Ré:

Alors la valeur de l'attribut n'est pas la chaîne vide, ni le nom canonique de l'attribut:

edName.attributes.required = [object Attr]

C'est parce requiredque dans ce code se trouve un objet attribut , pas une chaîne; attributesest un NamedNodeMapdont les valeurs sont des Attrobjets . Pour obtenir la valeur de l'un d'entre eux, vous regarderiez sa valuepropriété. Mais pour un attribut booléen, la valeur n'est pas pertinente; l'attribut est soit présent dans la carte (vrai), soit absent (faux).

Donc, si ce required n'était pas reflété, vous le définiriez en ajoutant l'attribut:

element.setAttribute("required", "");

... qui est l'équivalent de element.required = true. Vous l'effaceriez en le supprimant entièrement:

element.removeAttribute("required");

... qui est l'équivalent de element.required = false.

Mais nous n'avons pas à faire cela avec required, car cela se reflète.

TJ Crowder
la source
104

Version courte

element.setAttribute("required", "");    //turns required on
element.required = true;                 //turns required on through reflected attribute
jQuery(element).attr('required', '');    //turns required on
$("#elementId").attr('required', '');    //turns required on

element.removeAttribute("required");     //turns required off
element.required = false;                //turns required off through reflected attribute
jQuery(element).removeAttr('required');  //turns required off
$("#elementId").removeAttr('required');  //turns required off

if (edName.hasAttribute("required")) { }  //check if required
if (edName.required) { }                 //check if required using reflected attribute

Version longue

Une fois que TJ Crowder a réussi à signaler les propriétés reflétées , j'ai appris que la syntaxe suivante est incorrecte :

element.attributes["name"] = value; //bad! Overwrites the HtmlAttribute object
element.attributes.name = value;    //bad! Overwrites the HtmlAttribute object
value = element.attributes.name;    //bad! Returns the HtmlAttribute object, not its value
value = element.attributes["name"]; //bad! Returns the HtmlAttribute object, not its value

Vous devez passer par element.getAttributeet element.setAttribute:

element.getAttribute("foo");         //correct
element.setAttribute("foo", "test"); //correct

C'est parce que l'attribut contient en fait un objet HtmlAttribute spécial :

element.attributes["foo"];           //returns HtmlAttribute object, not the value of the attribute
element.attributes.foo;              //returns HtmlAttribute object, not the value of the attribute

En définissant une valeur d'attribut sur "true", vous la définissez par erreur sur un objet String , plutôt que sur l' objet HtmlAttribute dont il a besoin:

element.attributes["foo"] = "true";  //error because "true" is not a HtmlAttribute object
element.setAttribute("foo", "true"); //error because "true" is not an HtmlAttribute object

Conceptuellement, l'idée correcte (exprimée dans un langage typé) est:

HtmlAttribute attribute = new HtmlAttribute();
attribute.value = "";
element.attributes["required"] = attribute;

C'est pourquoi:

  • getAttribute(name)
  • setAttribute(name, value)

exister. Ils font le travail sur l'attribution de la valeur à l'objet HtmlAttribute à l'intérieur.

En plus de cela, certains attributs sont reflétés . Cela signifie que vous pouvez y accéder plus facilement à partir de Javascript:

//Set the required attribute
//element.setAttribute("required", ""); 
element.required = true;

//Check the attribute
//if (element.getAttribute("required")) {...}
if (element.required) {...}

//Remove the required attribute
//element.removeAttribute("required");
element.required = false;

Ce que vous ne voulez pas faire, c'est utiliser la .attributescollection par erreur :

element.attributes.required = true;     //WRONG!
if (element.attributes.required) {...}  //WRONG!
element.attributes.required = false;    //WRONG!

Cas de test

Cela a conduit à des tests autour de l'utilisation d'un requiredattribut, en comparant les valeurs renvoyées par l'attribut et la propriété reflétée

document.getElementById("name").required;
document.getElementById("name").getAttribute("required");

avec des résultats:

HTML                         .required        .getAttribute("required")
==========================   ===============  =========================
<input>                      false (Boolean)  null (Object)
<input required>             true  (Boolean)  "" (String)
<input required="">          true  (Boolean)  "" (String)
<input required="required">  true  (Boolean)  "required" (String)
<input required="true">      true  (Boolean)  "true" (String)
<input required="false">     true  (Boolean)  "false" (String)
<input required="0">         true  (Boolean)  "0" (String)

Essayer d'accéder .attributesdirectement à la collection est une erreur. Il renvoie l'objet qui représente l'attribut DOM:

edName.attributes["required"] => [object Attr]
edName.attributes.required    => [object Attr]

Cela explique pourquoi vous ne devriez jamais parler .attributesdirectement à la collecte. Vous ne manipulez pas les valeurs des attributs, mais les objets qui représentent les attributs eux-mêmes.

Comment définir requis?

Quelle est la bonne façon de définir requiredun attribut? Vous avez deux choix, soit la propriété reflétée , soit en définissant correctement l'attribut:

element.setAttribute("required", "");         //Correct
edName.required = true;                       //Correct

À proprement parler, toute autre valeur "définit" l'attribut. Mais la définition des Booleanattributs dicte qu'il ne doit être défini que sur la chaîne vide ""pour indiquer true . Les méthodes suivantes fonctionnent toutes pour définir l' attribut required booléen ,

mais ne les utilisez pas:

element.setAttribute("required", "required"); //valid, but not preferred
element.setAttribute("required", "foo");      //works, but silly
element.setAttribute("required", "true");     //Works, but don't do it, because:
element.setAttribute("required", "false");    //also sets required boolean to true
element.setAttribute("required", false);      //also sets required boolean to true
element.setAttribute("required", 0);          //also sets required boolean to true

Nous avons déjà appris qu'essayer de définir l'attribut directement est une erreur:

edName.attributes["required"] = true;       //wrong
edName.attributes["required"] = "";         //wrong
edName.attributes["required"] = "required"; //wrong
edName.attributes.required = true;          //wrong
edName.attributes.required = "";            //wrong
edName.attributes.required = "required";    //wrong

Comment effacer requis?

L'astuce lorsque vous essayez de supprimer l' requiredattribut est qu'il est facile de l'activer accidentellement:

edName.removeAttribute("required");     //Correct
edName.required = false;                //Correct

Avec les moyens invalides:

edName.setAttribute("required", null);    //WRONG! Actually turns required on!
edName.setAttribute("required", "");      //WRONG! Actually turns required on!
edName.setAttribute("required", "false"); //WRONG! Actually turns required on!
edName.setAttribute("required", false);   //WRONG! Actually turns required on!
edName.setAttribute("required", 0);       //WRONG! Actually turns required on!

Lorsque vous utilisez la .requiredpropriété reflétée , vous pouvez également utiliser des valeurs «falsey» pour la désactiver et des valeurs de vérité pour l'activer. Mais tenez-vous-en au vrai et au faux pour plus de clarté.

Comment vérifier pour required?

Vérifiez la présence de l'attribut via la .hasAttribute("required")méthode:

if (edName.hasAttribute("required"))
{
}

Vous pouvez également le vérifier via la propriété Boolean Reflected .required:

if (edName.required)
{
}
Ian Boyd
la source
1
Quelle est la distinction entre les variables elementet edName?
faintsignal
1
L'un est où j'ai oublié de convertir le nom d'élément spécifique edName(c.-à-d. La zone de saisie du nom) en générique element.
Ian Boyd
10

Ce qui compte n'est pas l'attribut mais la propriété , et sa valeur est un booléen.

Vous pouvez le définir en utilisant

 document.getElementById("edName").required = true;
Denys Séguret
la source
10

Et la version jquery:

$('input').attr('required', true)
$('input').attr('required', false)

Je sais que c'est au-delà de la question, mais peut-être que quelqu'un trouvera cela utile :)

VladCovaliov
la source
2
en fait, utilisez à la prop()place de attr():)
Poul Kruijt
1
@PierreDuc Nous sommes en 2019 .. nous n'utilisons plus :)
a20
@ a20 la dernière fois que j'ai vérifié, je l'utilise toujours. Donc, je suppose que vous vous trompez
Poul Kruijt
Je plaisantais avec mon frère ... désolé!
a20
3
let formelems = document.querySelectorAll('input,textarea,select');
formelems.forEach((formelem) => {
  formelem.required = true;

});

Si vous souhaitez créer toutes les entrées, zones de texte et sélectionner les éléments requis.

Kyle Pennell
la source
-2

essayez ceci ...

document.getElementById("edName").required = true;
Vijay
la source