¿Cómo configurar el atributo requerido HTML5 en Javascript?

93

Estoy tratando de marcar un textcuadro de entrada como se requiere en Javascript.

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

Si el campo está inicialmente marcado como required:

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

cuando el usuario intenta enviar, recibe un error de validación:

ingrese la descripción de la imagen aquí

Pero ahora quiero establecer el requiredatributo en "tiempo de ejecución" , a través de Javascript:

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

con el script correspondiente:

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

Excepto cuando envío ahora, no hay verificación de validación, no hay bloqueo.

¿Cuál es la forma correcta de establecer un atributo booleano de validación de HTML5 ?

jsFiddle

¿Cuál es el valor del atributo, preguntas?

El requiredatributo de validación de HTML5 está documentado como Boolean:

4.10.7.3.4 El requiredatributo

El requiredatributo es un atributo booleano . Cuando se especifica, el elemento es obligatorio.

Hay muchas dudas sobre cómo definir un booleanatributo. Las notas de la especificación HTML5:

La presencia de un atributo booleano en un elemento representa el valor verdadero y la ausencia del atributo representa el valor falso.

Si el atributo está presente, su valor debe ser la cadena vacía o un valor que sea una coincidencia ASCII que no distinga entre mayúsculas y minúsculas para el nombre canónico del atributo, sin espacios en blanco al principio o al final.

Esto significa que puede especificar un atributo required booleano de dos formas diferentes:

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

Pero ¿cuál es el valor del atributo de verdad ?

Cuando mires mi jsFiddle de este problema , notarás que si el requiredatributo está definido en el marcado:

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

Entonces el valor del atributo no es la cadena vacía, ni el nombre canónico del atributo:

edName.attributes.required = [object Attr]

Eso podría llevar a una solución.

Ian Boyd
fuente
4
No entiendo por qué no lo permiten required="false", ¿alguna vez escribieron una plantilla antes de escribir el estándar? Los atributos condicionales suelen ser una molestia, es mucho más fácil poner ese booleano en el valor del atributo ...
Christophe Roussy
¿Es posible mostrar manualmente ese texto sobre la entrada requerida: "Por favor, complete este campo"?
zygimantus

Respuestas:

121

requiredes una propiedad reflejada (como id, name, type, y tal), por lo que:

element.required = true;

... donde elementestá el inputelemento DOM real , por ejemplo:

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

(Solo para completar).

Re:

Entonces el valor del atributo no es la cadena vacía, ni el nombre canónico del atributo:

edName.attributes.required = [object Attr]

Eso es porque requireden ese código hay un objeto de atributo , no una cadena; attributeses un NamedNodeMapcuyos valores son Attrobjetos . Para obtener el valor de uno de ellos, miraría su valuepropiedad. Pero para un atributo booleano, el valor no es relevante; el atributo está presente en el mapa (verdadero) o no está presente (falso).

Entonces, si required no estuviera reflejado, lo establecería agregando el atributo:

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

... que es el equivalente de element.required = true. Lo borrarías eliminándolo por completo:

element.removeAttribute("required");

... que es el equivalente de element.required = false.

Pero no tenemos por qué hacer eso required, ya que se refleja.

TJ Crowder
fuente
¿Puedes agregar algo sobre .prop aquí?
mplungjan
@mplungjan - ¿No estoy seguro de a qué te refieres ...? jQuery?
TJ Crowder
Sí, porque es confuso que prod no funcione en DOM
mplungjan
110

Version corta

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

Versión larga

Una vez que TJ Crowder logró señalar las propiedades reflejadas , aprendí que la siguiente sintaxis es incorrecta :

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

Usted debe ir a través de element.getAttributey element.setAttribute:

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

Esto se debe a que el atributo en realidad contiene un objeto HtmlAttribute especial :

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

Al establecer un valor de atributo en "verdadero", lo está estableciendo por error en un objeto String , en lugar del objeto HtmlAttribute que requiere:

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

Conceptualmente, la idea correcta (expresada en un lenguaje mecanografiado) es:

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

Esta es la razón por:

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

existe. Ellos hacen el trabajo de asignar el valor al objeto HtmlAttribute dentro.

Además de esto, se reflejan algunos atributos . Esto significa que puede acceder a ellos más fácilmente desde 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;

Lo que no quieres hacer es usar la .attributescolección por error :

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

Casos de prueba

Esto llevó a realizar pruebas en torno al uso de un requiredatributo, comparando los valores devueltos a través del atributo y la propiedad reflejada.

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

con resultados:

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)

Intentar acceder a la .attributescolección directamente es incorrecto. Devuelve el objeto que representa el atributo DOM:

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

Esto explica por qué nunca debe hablar .attributesdirectamente con el cobrador. No está manipulando los valores de los atributos, sino los objetos que representan los atributos en sí.

¿Cómo configurar requerido?

¿Cuál es la forma correcta de establecer requiredun atributo? Tiene dos opciones, ya sea la propiedad reflejada o estableciendo correctamente el atributo:

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

Estrictamente hablando, cualquier otro valor "establecerá" el atributo. Pero la definición de Booleanatributos dicta que solo debe establecerse en la cadena vacía ""para indicar verdadero . Los siguientes métodos funcionan todos para establecer el atributo required booleano ,

pero no los uses :

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

Ya aprendimos que intentar establecer el atributo directamente es incorrecto:

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

¿Cómo borrar los requisitos?

El truco al intentar eliminar el requiredatributo es que es fácil activarlo accidentalmente:

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

Con las formas inválidas:

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!

Al usar la .requiredpropiedad reflejada , también puede usar cualquier valor "falsey" para desactivarla y valores de verdad para activarla. Pero limítese a verdadero y falso para mayor claridad.

Cómo comprobar para required?

Verifique la presencia del atributo a través del .hasAttribute("required")método:

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

También puede verificarlo a través de la propiedad reflejada booleana.required :

if (edName.required)
{
}
Ian Boyd
fuente
1
¿Cuál es la distinción entre las variables elementy edName?
señal de desmayo
1
Uno es donde olvidé convertir el nombre del elemento específico edName(es decir, el cuadro de entrada de nombre) en el genérico element.
Ian Boyd
" Debe seguir element.getAttributey element.setAttribute:" Para mayor claridad, puede usar attributes NamedNodeMappara cambiar el valor de un atributo si sabe que el atributo ya está allí, pero no puede usarlo para agregar un atributo que no está allí (o para eliminar uno que es). Entonces, ese enfoque no es útil para atributos booleanos como requiredporque lo que les importa es si están allí, no cuál es su valor. Pero sí, las propiedades reflejadas suelen ser más fáciles. :-)
TJ Crowder
10

Lo que importa no es el atributo, sino la propiedad , y su valor es un booleano.

Puedes configurarlo usando

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

Y la versión de jquery:

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

Sé que está más allá de toda duda, pero tal vez a alguien le resulte útil :)

vladCovaliov
fuente
2
en realidad, use en prop()lugar de attr():)
Poul Kruijt
1
@PierreDuc Es 2019 ... ya no usamos :)
a20
@ a20 la última vez que lo comprobé, todavía lo estoy usando. Entonces, supongo que estás equivocado
Poul Kruijt
Estaba bromeando con mi hermano ... ¡lo siento!
a20
3
let formelems = document.querySelectorAll('input,textarea,select');
formelems.forEach((formelem) => {
  formelem.required = true;

});

Si desea hacer que todos los elementos de entrada, área de texto y selección sean necesarios.

Kyle Pennell
fuente
-2

prueba esto ...

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