0

I am trying to use jQuery inside an Angular Elements web component with ShadowDom encapsulation and running into problems with internet explorer, specifically IE11. An error is triggered when resolving to the shadowRoot and then using the jQuery find method with a selector other than an ID. The error message is:

Unable to get property 'length' of undefined or null reference

I created a simple page to isolate the problem and was able to reproduce the same error.

    <h2>Hello from outside the Shadow DOM!</h2>

    <div class='parent'></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/shadydom/1.1.0/shadydom.min.js"></script>
    <script
      src="https://code.jquery.com/jquery-3.4.1.js"
      integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
      crossorigin="anonymous"></script>

    <script>
      // Setup an element in the shadow DOM
      var element = $('.parent')[0];
      var shadow = element.attachShadow({mode: 'open'});

      var text = document.createElement('span');
      text.id = 'subtitle';
      text.textContent = 'Hello from inside the Shadow DOM!';

      shadow.appendChild(text);      
      //-- End Setup

      // This is how the web component code is getting access to the shadow root
      var shadowRoot = $(element.shadowRoot);

      // No problems with this find call
      var subtitle = shadowRoot.find('#subtitle');

      // IE Bug is triggered here
      var span = shadowRoot.find('span');

      console.log('jQuery set count: ' + span.length);
    </script>

And here is the stack when the error occurs:

Error Stack Trace

Is this a known issue with jQuery and piercing the shadow DOM in IE11? Are there any solutions?

redfish819
  • 31
  • 6

2 Answers2

1

I found a workaround that works consistently on IE11 and Chrome. Putting the shadow DOM elements within a container div that has an ID allows for resolving to the container and finding the elements from that context. Here is the updated code:

<script>
  // Setup an element in the shadow dom
  var element = $('.parent')[0];
  var shadow = element.attachShadow({mode: 'open'});

  var container = document.createElement('div');
  container.id = 'container';
  container.innerHTML = '<span>Hello from inside the Shadow DOM!</span>'

  shadow.appendChild(container);      
  //-- End Setup

  // This is how site search get access to the shadow root
  var shadowRoot = $(element.shadowRoot);

  // Use the shadow root to resolve to the cotnainer by ID 
  // and then finding any other elements in the shadow DOM
  // works as expected.
  var container = shadowRoot.find('#container');
  var span = container.find('span');

  console.log('jQuery set count: ' + span.length);

</script> 
redfish819
  • 31
  • 6
0

After using F12 developer tools to debug the javascript, we can see that the span is undefined. So, it will show the "Unable to get property 'length' of undefined or null reference" error.

To solve this error, please try to find the span element from the "element" variable, instead of from the "shadowRoot". please check the following code:

<script>
    // Setup an element in the shadow DOM
    var element = $('.parent')[0];
    var shadow = element.attachShadow({ mode: 'open' });

    var text = document.createElement('span');
    text.id = 'subtitle';
    text.className = "spanitem";
    text.textContent = 'Hello from inside the Shadow DOM!';

    shadow.appendChild(text);
    //-- End Setup

    // This is how the web component code is getting access to the shadow root
    var shadowRoot = $(element.shadowRoot);

    // No problems with this find call
    var subtitle = shadowRoot.find('#subtitle');

    // 
    var span = $(element).find('span');

    console.log('jQuery set count: ' + span.length); 
</script>
Zhi Lv
  • 18,845
  • 1
  • 19
  • 30
  • Thanks for your answer. I ran your changes and see that it provides the expected result in IE11 but does not work correctly in Chrome. In Chrome the span.length is equal to zero, which makes sense because the shadow DOM is supposed to prevent the selection of elements it contains from queries performed outside of it. Referencing the shadowRoot is how one should access its elements. It looks like jQuery doesn't work correctly with the shadow DOM in a number of ways in IE11. – redfish819 Mar 27 '20 at 16:11