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:
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
The HTML5 validation required
attribute is documented as a Boolean
:
4.10.7.3.4 The
required
attributeThe
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
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.
Required attribute: If you want to make an input mandatory to be entered by the user, you can use the required attribute. This attribute can be used with any input type such as email, URL, text, file, password, checkbox, radio, etc. This can help to make any input field mandatory.
The required attribute is a boolean attribute. When present, it specifies that an input field must be filled out before submitting the form. Note: The required attribute works with the following input types: text, search, url, tel, email, password, date pickers, number, checkbox, radio, and file.
However, if one is handling mouse events, for instance, using JS, they can set the "required" attribute to "True" or "False" using the ". prop()" method. e.g.
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.
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
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!
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.
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 edName.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
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.
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) { }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With