Can I access the shadow DOM using jQuery?

I defined a component with polymer like this:

<polymer-element name="my-component"> <template> <div id='test'>CONTENT</div> </template>
</polymer-element>

Now I want to access the shadow dom, for example: to get the content of div id='test'

var x = $("div#test").html();

The given code doesn't work. Can I access the shadow dom with jquery?

10 Answers

No, not outside of the Polymer element.

After reading up on Polymer, it looks like you can only have access to the shadow-DOM of Polymer elements in scripts within the Polymer element. The Polymer docs on Automatic node finding say:

Every node in a component’s shadow DOM that is tagged with an id attribute is automatically referenced in the component’s this.$ hash.

This means you can add a <script> tag as a sibling to <template> where this.$.test will be the element you want.

<polymer-element name="my-component"> <template> <div id='test'>CONTENT</div> </template> <script> Polymer('my-component', { logNameValue: function () { console.log('polymer element', this.$.test); console.log('jQuery wrapper of polymer element', $(this.$.test)); } }); </script>
</polymer-element>
2

You can use $('body /deep/ your-selector') pattern to pierce through shadow DOM and get Jquery to work inside it.

update: So far I have only managed to make this work on chrome for desktop. I believe, other browsers do not support the /deep/ combinator.

update 2: /deep/ combinator is deprecated and should not be used anymore. It is scheduled to be removed from Chrome.

3

I'm able to access the shadowRoot elements in Chrome like so:

$("#idOfElementInShadowRoot", $("#idOfShadowRootElement").shadowRoot)

Got the idea from Jquery: How to select only within a selection?

2

I think this works for me...

$('polymer-element::shadow #test')

Only tested it on chrome though

1

You can do it like this:

$("#example", this.shadowRoot).DataTable();

This worked for me

$(element)[0].shadowRoot

I wrote simple helper in TypeScript to solve this problem:

class DomUtils { public static getShadowElementById(id: string):any { try { // Try to get it by simple id in case of browser doesn't support shadow DOM var element = $("#" + id); if (element.length <= 0) { // Support Chrome browser element = $("body /deep/ #" + id); } return element; } catch (error) { console.log("Error: " + error + ", while trying to get shadow element with id: " + id); return null; } }
} 

Usage:

var element = DomUtils.getShadowElementById('mainContainer');

Tested on desktop Chrome, Internet Explorer, Firefox

0

Use something like this:

jQuery.fn.extend({ shadowRoot: function() { return $(this.get(0).shadowRoot); },
});

and call:

$("my-element").shadowRoot());

this is my simple function to change capcha in shadow-root

const get_captcha = (CustomElement)=>{	var src = `./app/create_captcha/${chance.natural()}`;	var rootElement = $(CustomElement)[0].shadowRoot;	var captchaElement = $(rootElement).find('#img_captcha');	$(captchaElement).attr('src',src);
};

For what it's worth tossing this into the list of answers since it's ultimately what I used.

// following line assumes shadow content has only one <body> tag...
// ...otherwise filter by whatever makes sense for your code
var $shadowBody = $($("#shadow-root-elem")[0].shadowRoot.childNodes).filter("body");
// get the elem in the shadow content that I need/want
var $elemInShadowBody = $shadowBody.find(".selector.for.elem.in.shadow.body")

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like