1

When a form field that has standard HTML validation constraints placed on it (pattern & required in this case) gets inserted into the DOM via the .innerHTML property, the field does not validate. I am aware of the difference between creating an element with .innerHTML and document.createElement() with regards to event registration, but have not encountered this side-effect before.

In my particular situation, there is a very large amount of HTML that must be inserted into the DOM and creating all of it via document.createElement(), then setting all of the node properties and using .appendChild() to establish the proper heirarchy is not desirable.

Why is this and, if it is possible, how can it be overcome (no jQuery answers please)?

NOTE: I am aware of HTML <template>, but since there is no support for it in any version of IE, it won't work for me.

In the snippet below, the first field will work as it should, but the second one demonstrates what I'm talking about. It won't validate if you manually enter data (5 digits in this case) or if you press the button to have valid data be dynamically inserted.

document.querySelector("div").innerHTML = `<input type="text" id="broken" name="zip" pattern="\d{5}" required placeholder="I don't.">`;

document.querySelector("input[type='button']").addEventListener("click", function(){
  document.getElementById("broken").value = "12345";  // 12345 or "12345" - doesn't matter
});
:required { background:#f99; }
:valid    { background:green; }
input[type=text] { width:250px; }
<input type="text" id="zip2" name="zip2" pattern="\d{5}" required placeholder="I work as I should (5 digits please).">
<div></div>
<input type="button" value="Populate">
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Do not create browser **controls** with innerHTML - they are not document elements, and they are not exactly pure HTML, they are controls. Controls may get created and render on the document, but sometimes the will fail to get initialized or at least their browser automation may not trigger. innerHTML is perfect for pure HTML elements, for anything else, use DOM. – Bekim Bacaj Mar 09 '18 at 19:54
  • 1
    @BekimBacaj I appreciate your input (no pun intended), but your description is not exactly correct. There is no such thing as a "control" in the world of HTML. `.innerHTML` does, in fact, create DOM elements and they are "pure" html. These elements are accessible as `node`s and can be interacted with as normal. The only issues with `.innerHTML` are event registration and performance slowdowns due to re-paints and re-flows. – Scott Marcus Mar 09 '18 at 19:56
  • 1
    @BekimBacaj When you use `.innerHTML` you are simply asking the user-agent to parse a string for HTML content and then deal with that HTML as it normally would. This is no different than what the UA does when the page is first loaded with the exception that the newly parsed HTML must be "injected" into the existing DOM, so there are timing issues that come up (hence the event registration issues) as well as rendering issues. – Scott Marcus Mar 09 '18 at 19:59
  • 1
    @BekimBacaj Having said all of that, I agree that using the DOM API to create and update the DOM is generally the better approach, as it is cleaner and usually results in more scalable code. – Scott Marcus Mar 09 '18 at 20:01
  • 1. innerHTML parser is faster than DOM in many cases. 2. There are controls All form elements are controls with their corresponding native automation behavior. They are supposed to work without JavaScript. 3. There are HTML Tags which are of a higher category than simple browser controls. IFRAME comes to mind, that's a full fledged browser window/tab. 4. innerHTML does not DOM elements, DOM API mirrors them after they have been parsed by a global HTML parser or the local innerHTML parser. – Bekim Bacaj Mar 09 '18 at 20:05
  • I'm sorry that SO somehow managed to shred and shuffle the content of my reply. – Bekim Bacaj Mar 09 '18 at 20:09
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/166561/discussion-between-scott-marcus-and-bekim-bacaj). – Scott Marcus Mar 09 '18 at 20:09
  • nah, let's not - sorry for disturbing your knowledge. People simply don't want to know these things, because most of the time, they don't need to! – Bekim Bacaj Mar 09 '18 at 20:13
  • 1
    @BekimBacaj I encourage you to look at my comments in the chat. I've been doing this for a very long time and I am quite confident that you are confusing what happens between the OS and the UA with what happens in the UA's DOM Parser and JS engine. You are also very incorrect about the results of `.innerHTML` and how the DOM gets built and updated. – Scott Marcus Mar 09 '18 at 20:29

1 Answers1

3

Missing backslash on your regexp:

"\\d{5}"
 ^

Look how the backslash disappears:

console.log(`<input type="text" id="broken" name="zip" pattern="\d{5}" required placeholder="I don't.">`)

Now everything is working as expected.

document.querySelector("div").innerHTML = `<input type="text" id="broken" name="zip" pattern="\\d{5}" required placeholder="I don't.">`;   

document.querySelector("input[type='button']").addEventListener("click", function(){
  document.getElementById("broken").value = "12345";  // 12345 or "12345" - doesn't matter
});
:required { background:#f99; }
:valid    { background:green; }
input[type=text] { width:250px; }
<input type="text" id="zip2" name="zip2" pattern="\d{5}" required placeholder="I work as I should (5 digits please).">
<div></div>
<input type="button" value="Populate">
Ele
  • 33,468
  • 7
  • 37
  • 75