139

I am trying to mark a text input box as required in Javascript.

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

If the field is initially marked as required:

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

when the user tries to submit they are given a validation error:

enter image description here

But now I want to set the required attribute at "runtime", through Javascript:

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

with the corresponding script:

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

Except when I submit now, there is no validation check, no block.

What is the correct way to set an HTML5 validation boolean attribute?

jsFiddle

What's the value of the attribute, you ask?

The HTML5 validation required attribute is documented as a Boolean:

4.10.7.3.4 The required attribute

The required attribute is a boolean attribute. When specified, the element is required.

There is a lot of hand-wringing about how to define a boolean attribute. The HTML5 spec notes:

The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.

If the attribute is present, its value must either be the empty string or a value that is an ASCII case-insensitive match for the attribute's canonical name, with no leading or trailing whitespace.

This means that you can specify a required boolean attribute two different ways:

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

But what is the value of the attribute really?

When you look at my jsFiddle of this problem, you'll notice that if the required attribute is defined in the markup:

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

Then the attribute's value is not the empty string, nor the canonical name of the attribute:

edName.attributes.required = [object Attr]

That might lead to a solution.

3
  • 5
    I do not understand why they do not allow required="false", did they ever write a template before writing the standard ? Conditional attributes are usually a pain, it is way easier to just put that boolean in the attribute value... Commented Dec 14, 2015 at 11:41
  • Is it possible manually show that text over required input: "Please fill this out this field."? Commented Jun 22, 2017 at 11:33
  • 2
    @ChristopheRoussy Agreed. People who write standards (HTML, CSS and even JS) are completely twisted minds. Those languages are a complete mess, but too widely used to be easily replaced, unfortunately... Commented Aug 3, 2022 at 7:50

7 Answers 7

179

required is a reflected property (like id, name, type, and such), so:

element.required = true;

...where element is the actual input DOM element, e.g.:

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

(Just for completeness.)

Re:

Then the attribute's value is not the empty string, nor the canonical name of the attribute:

edName.attributes.required = [object Attr]

That's because required in that code is an attribute object, not a string; attributes is a NamedNodeMap whose values are Attr objects. To get the value of one of them, you'd look at its value property. But for a boolean attribute, the value isn't relevant; the attribute is either present in the map (true) or not present (false).

So if required weren't reflected, you'd set it by adding the attribute:

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

...which is the equivalent of element.required = true. You'd clear it by removing it entirely:

element.removeAttribute("required");

...which is the equivalent of element.required = false.

But we don't have to do that with required, since it's reflected.

Sign up to request clarification or add additional context in comments.

Comments

165

Short version

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

Long Version

Once T.J. Crowder managed to point out reflected properties, i learned that following syntax is wrong:

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

You must go through element.getAttribute and element.setAttribute:

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

This is because the attribute actually contains a special HtmlAttribute object:

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

By setting an attribute value to "true", you are mistakenly setting it to a String object, rather than the HtmlAttribute object it requires:

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

Conceptually the correct idea (expressed in a typed language), is:

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

This is why:

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

exist. They do the work on assigning the value to the HtmlAttribute object inside.

On top of this, some attribute are reflected. This means that you can access them more nicely from 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;

What you don't want to do is mistakenly use the .attributes collection:

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

Testing Cases

This led to testing around the use of a required attribute, comparing the values returned through the attribute, and the reflected property

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

with results:

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)

Trying to access the .attributes collection directly is wrong. It returns the object that represents the DOM attribute:

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

This explains why you should never talk to the .attributes collect directly. You're not manipulating the values of the attributes, but the objects that represent the attributes themselves.

How to set required?

What's the correct way to set required on an attribute? You have two choices, either the reflected property, or through correctly setting the attribute:

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

Strictly speaking, any other value will "set" the attribute. But the definition of Boolean attributes dictate that it should only be set to the empty string "" to indicate true. The following methods all work to set the required Boolean attribute,

but do not use them:

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

We already learned that trying to set the attribute directly is wrong:

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

How to clear required?

The trick when trying to remove the required attribute is that it's easy to accidentally turn it on:

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

With the invalid ways:

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!

When using the reflected .required property, you can also use any "falsey" values to turn it off, and truthy values to turn it on. But just stick to true and false for clarity.

How to check for required?

Check for the presence of the attribute through the .hasAttribute("required") method:

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

You can also check it through the Boolean reflected .required property:

if (edName.required)
{
}

3 Comments

What is the distinction between the variables element and edName?
One is where i forgot to convert specific element name edName (i.e. Name Input Box) into the generic element.
"You must go through element.getAttribute and element.setAttribute:" Just for clarity, you can use the attributes NamedNodeMap to change an attribute's value if you know the attribute is already there, you just can't use it to add an attribute that isn't there (or to remove one that is). So that approach isn't useful for boolean attributes like required because what matters with them is whether they're there, not what their value is. But yes, reflected properties are usually easier. :-)
14

What matters isn't the attribute but the property, and its value is a boolean.

You can set it using

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

Comments

10

And the jquery version:

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

I know it's beyond the question, but maybe someone will find this helpful :)

4 Comments

actually, use prop() instead of attr() :)
@PierreDuc It's 2019 .. we don't use :) any more
@a20 last time I checked, I am still using it. So, I guess you are wrong
I was kidding my brother .. sorry!
3
let formelems = document.querySelectorAll('input,textarea,select');
formelems.forEach((formelem) => {
  formelem.required = true;

});

If you wish to make all input, textarea, and select elements required.

Comments

0

try out this..

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

Comments

0

if you want to set input as required in some cases and not required in other cases just I suggest to set the input to hard coded as required and display it "block" when needed and disable it to remove required effect and display it "none" as a code example :

    <script>
        function removeReuired()
        {
          var x = document.getElementById("select").value ;
        if(x == "a")
        {
            alert("a")
            document.getElementById("g9").style.display = "block";
            element2 = document.getElementById("g9input");
            if(element2.disabled)
            {
              document.getElementById("g9input").disabled = false;  
            }
        }
        else
        {
            alert("b")
            //document.getElementById("g9").remove() ;// if you use remove then you need to rebuild the element again (not recommended )
            document.getElementById("g9input").disabled = true;
             document.getElementById("g9").style.display = "none";
        }
            
        }
    </script>
    <form action="test1.php"> 
    <select name="select" id="select" onchange="removeReuired()">
        <option></option>
        <option value="a">a</option>
        <option value="b">b</option>
    </select>
    <div id="g9"> 
    <input id="g9input" required  type="checkbox">
    hiiii
    </div>
    <button type="submit">Submit</button>
    </form> 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.