문제

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?

도움이 되었습니까?

해결책

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>

다른 팁

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")
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top