Question

I'm having trouble getting JavaScript to run properly within Shadow DOM elements I'm defining. Given the following code:

<template id='testTemplate'>
 <div id='test'>Click to say hi</div>
 <script>
  var elem = document.querySelector('#test');
  elem.addEventListener('click', function(e) {
     alert("Hi there");
  });
</script>
</template>

<div id="testElement">Host text</div>

<script>
  var shadow = document.querySelector('#testElement').createShadowRoot();
  var template = document.querySelector('#testTemplate');
  shadow.appendChild(template.content.cloneNode(true));
</script>

document.querySelector is returning null. If I wrap it in document.onload it no longer throws the error, but clicking the div doesn't launch the alert, either.

  1. Is document.onload the proper way to handle when my code runs in this case?
  2. Is this the proper way to embed javascript for shadow dom elements?
Was it helpful?

Solution

Shadow DOM tree

You must bind your eventHandler inside the template tag to #testElement:

var elem = document.querySelector('#testElement');

Meaning to the original element / ShadowHost. That is, because Events from ShadowElements appear as if they originated by the ShadowHost.

Javascript is actually not scoped inside of ShadowDOM-Trees. See for example this blog entry, which covers exactly that topic:

Remember when I spent all of that time explaining how Shadow DOM CSS was encapsulated and protected from the parent document and how awesome that all was? You might also think that JavaScript works the same way—I did at first—but that’s actually not the case. [...] http://robdodson.me/blog/2013/09/02/shadow-dom-javascript/

As an explanation for rearranging the events to the ShadowHost the author writes:

This is because events coming from shadow nodes have to be retargeted otherwise they would break encapsulation. If the event target continued to point at #shadow-text then anyone could dig around inside of our Shadow DOM and start messing things up. http://robdodson.me/blog/2013/09/02/shadow-dom-javascript/

I suppose it is a good idea to read other articles of this blog too, as it seems to cover the topic pretty well.

Custom elements

With custom HTML elements you have the ability to use Javascript inside of custom HTML elements, see for example this answer on Stackoverflow.

Basically you must create a complete new HTML element. A tutorial is available at html5rocks. I think this is how for example the Polymer project provides its custom events.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top