Como definir o atributo obrigatório HTML5 em Javascript?

89

Estou tentando marcar uma textcaixa de entrada como necessária em Javascript.

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

Se o campo for inicialmente marcado como required:

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

quando o usuário tenta enviar, recebe um erro de validação:

insira a descrição da imagem aqui

Mas agora quero definir o requiredatributo em "tempo de execução" , por meio de Javascript:

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

com o script correspondente:

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

Exceto quando eu enviar agora, não há verificação de validação, nem bloqueio.

Qual é a maneira correta de definir um atributo booleano de validação HTML5 ?

jsFiddle

Qual é o valor do atributo, você pergunta?

O requiredatributo de validação HTML5 é documentado como Boolean:

4.10.7.3.4 O requiredatributo

O requiredatributo é um atributo booleano . Quando especificado, o elemento é obrigatório.

Há muitas dúvidas sobre como definir um booleanatributo. As notas de especificação do HTML5:

A presença de um atributo booleano em um elemento representa o valor verdadeiro e a ausência do atributo representa o valor falso.

Se o atributo estiver presente, seu valor deve ser a string vazia ou um valor que não faz distinção entre maiúsculas e minúsculas ASCII para o nome canônico do atributo, sem nenhum espaço em branco à esquerda ou à direita.

Isso significa que você pode especificar um atributo required booleano de duas maneiras diferentes:

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

Mas qual é realmente o valor do atributo ?

Ao examinar meu jsFiddle sobre esse problema , você notará que, se o requiredatributo estiver definido na marcação:

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

Então, o valor do atributo não é a string vazia, nem o nome canônico do atributo:

edName.attributes.required = [object Attr]

Isso pode levar a uma solução.

Ian Boyd
fonte
4
Não entendo por que eles não permitem required="false". Eles escreveram um modelo antes de escrever o padrão? Atributos condicionais geralmente são uma dor, é muito mais fácil simplesmente colocar esse booleano no valor do atributo ...
Christophe Roussy
É possível mostrar manualmente esse texto sobre a entrada obrigatória: "Preencha este campo."?
zygimantus

Respostas:

116

requiredé uma propriedade reflectiu (como id, name, type, e tal), da seguinte forma:

element.required = true;

... onde elementestá o inputelemento DOM real , por exemplo:

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

(Apenas para completar.)

Ré:

Então, o valor do atributo não é a string vazia, nem o nome canônico do atributo:

edName.attributes.required = [object Attr]

Isso porque requirednesse código há um objeto de atributo , não uma string; attributesé um NamedNodeMapcujos valores são Attrobjetos . Para obter o valor de um deles, você deve olhar sua valuepropriedade. Mas para um atributo booleano, o valor não é relevante; o atributo está presente no mapa (verdadeiro) ou ausente (falso).

Portanto, se required não fosse refletido, você o configuraria adicionando o atributo:

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

... que é equivalente a element.required = true. Você o limparia removendo-o inteiramente:

element.removeAttribute("required");

... que é equivalente a element.required = false.

Mas não temos que fazer isso required, pois é refletido.

TJ Crowder
fonte
104

Versão curta

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

Versão longa

Depois que TJ Crowder conseguiu apontar as propriedades refletidas , aprendi que a seguinte sintaxe está errada :

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

Você deve passar element.getAttributee element.setAttribute:

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

Isso ocorre porque o atributo realmente contém um 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

Ao definir um valor de atributo como "true", você o está definindo por engano como um objeto String , em vez do objeto HtmlAttribute que ele requer:

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

Conceitualmente, a ideia correta (expressa em uma linguagem digitada) é:

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

Isso é por que:

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

existir. Eles fazem o trabalho de atribuir o valor ao objeto HtmlAttribute interno.

Além disso, alguns atributos são refletidos . Isso significa que você pode acessá-los mais facilmente em 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;

O que você não quer fazer é usar a .attributescoleção por engano :

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

Casos de Teste

Isso levou a testes em torno do uso de um requiredatributo, comparando os valores retornados por meio do atributo e a propriedade refletida

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

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

Tentar acessar a .attributescoleção diretamente é errado. Ele retorna o objeto que representa o atributo DOM:

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

Isso explica por que você nunca deve falar .attributesdiretamente com a cobrança. Você não está manipulando os valores dos atributos, mas os objetos que representam os próprios atributos.

Como configurar necessário?

Qual é a maneira correta de definir requiredem um atributo? Você tem duas opções, a propriedade refletida ou por meio da configuração correta do atributo:

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

A rigor, qualquer outro valor "definirá" o atributo. Mas a definição de Booleanatributos dita que só deve ser definido como a string vazia ""para indicar true . Todos os métodos a seguir funcionam para definir o atributo required booleano ,

mas não os use :

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

Já aprendemos que tentar definir o atributo diretamente é errado:

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

Como limpar necessário?

O truque ao tentar remover o requiredatributo é que é fácil ativá-lo acidentalmente:

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

Com as 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!

Ao usar a .requiredpropriedade refletida , você também pode usar quaisquer valores "falsey" para desativá-la e valores verdadeiros para ativá-la. Mas apenas se atenha a verdadeiro e falso para maior clareza.

Como verificar para required?

Verifique a presença do atributo por meio do .hasAttribute("required")método:

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

Você também pode verificar por meio da propriedade booleana refletida .required:

if (edName.required)
{
}
Ian Boyd
fonte
1
Qual é a diferença entre as variáveis elemente edName?
faintsignal
1
Um é onde eu esqueci de converter o nome do elemento específico edName(ou seja, caixa de entrada de nome) em genérico element.
Ian Boyd
10

O que importa não é o atributo, mas a propriedade , e seu valor é um booleano.

Você pode configurá-lo usando

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

E a versão do jquery:

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

Eu sei que está além de qualquer dúvida, mas talvez alguém ache isso útil :)

vladCovaliov
fonte
2
na verdade, use em prop()vez de attr():)
Poul Kruijt
1
@PierreDuc É 2019 .. não usamos mais :)
a20
@ a20 da última vez que verifiquei, ainda estou usando. Então, eu acho que você está errado
Poul Kruijt
Eu estava brincando com meu irmão .. desculpe!
a20
3
let formelems = document.querySelectorAll('input,textarea,select');
formelems.forEach((formelem) => {
  formelem.required = true;

});

Se você deseja fazer todas as entradas, textarea e selecionar os elementos necessários.

Kyle Pennell
fonte
-2

experimente isso ..

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