Domanda

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?

È stato utile?

Soluzione

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>

Altri suggerimenti

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.

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?

I think this works for me...

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

Only tested it on chrome though

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

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")
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top