1

I am trying to use the following code to execute a script from within shadowRoot.

const template = document.createElement('template');
template.innerHTML = `<script>console.log("hey");</script>`;
this.shadowRoot.appendChild(template.content);

I'm told creating a template should work, but this code doesn't appear to work in Chrome v71.

Cheetah
  • 13,785
  • 31
  • 106
  • 190
  • See answer at [Script inside shadow dom not working](https://stackoverflow.com/q/51101473/4600982) – Supersharp Jan 22 '19 at 23:22
  • @Supersharp - my example code that doesn't work is the same as the "solution 2" from that response...isn't it? – Cheetah Jan 23 '19 at 08:51
  • 1
    No, you use innerHTML while in solution it get a template element in the DOM – Supersharp Jan 23 '19 at 12:29
  • @Supersharp is correct. The innerHTML is stopping the script from executing. This is true even though you appendChild() the content. I would advise, however, that while it is not necessary to clone, the template, it is bad practice to `appendChild(template.content)` and instead `appendChild(template.content.cloneNode())`. Not doing so can lead to a lot of bugs, though this specific code sample does not need it. – Fuzzical Logic Feb 02 '19 at 00:13
  • I wrote a pretty thorough explanation about this [here](https://stackoverflow.com/a/72243722/6036546) with a workaround (that comes with some warnings). – Besworks May 14 '22 at 21:49

1 Answers1

0

The first thing to remember is that shadowDOM encapsulates DOM and CSS and NOT JavaScript.

The second thing to know is that you can not introduce script into the DOM by using .innerHTML. See this link. Instead the class that defines your component is how to encapsulate your JS code.

While you can't use .innerHTML you can create a script element and set its .textContent and then call .appendChild() for that.

const script = document.createElement('script');
script.textContent = `alert("hey");`;

const el = document.querySelector('.testing');
el.attachShadow({mode:'open'});
el.shadowRoot.appendChild(script);
<div class="testing"></div>

But, given #2 this probably is not what you really want to do.

Intervalia
  • 10,248
  • 2
  • 30
  • 60