batgerel.e
batgerel.e

Reputation: 857

How to get element from shadow-DOM

I have a problem with accessing to shadow-root. I need to get img but it doesn't work. Here is my page:

<link rel="import" href="/frontend/src/ui/breadcrumb.html">
<dom-module id="bread-crumb">
    <template>
        <style include="breadcrumb"></style>
        <div id="wrapper">
            <template is="dom-if" if="{{pageInfo.title}}">
                <div class="left">
                    <img id="img" src$="{{pageInfo.icon}}">
                    <span>{{pageInfo.title}} <strong>{{pageInfo.part}}</strong></span>
                </div>
            </template>
            <div class="links">
                <template is="dom-repeat" items="[[links]]">
                    <a class$="{{_getSelected(item.selected)}}" href$="{{item.link}}"> {{item.title}} </a>
                </template>
                <!-- <template is="dom-if" if="{{item.title}}">
                    <a href$=""
                </template> -->
            </div>
        </div>
    </template>
    <script>
    class BreadCrumb extends Polymer.Element {
        static get is() {
            return 'bread-crumb'
        }
        _getSelected(selected){
            return selected ? "selected" : "";
        }

        connectedCallback() {
            this._imageHide();
        }

        _imageHide() {
            let image = this.$.img;
            if(image.src == null || image.src == undefined)
                image.classList.add("hidden");
        }
    }

    customElements.define(BreadCrumb.is, BreadCrumb);
    </script>
</dom-module>

I tried this also let image = this.shadowRoot.querySelector('#img'); but it is not working too. And above throws a error:

Cannot read property 'img' of undefined

and i tried other way let image = this.shadowRoot.querySelector('#img'); this gives me:

Cannot read property 'querySelector' of null

What did i do wrong ? Any advice ?

Upvotes: 3

Views: 1815

Answers (1)

mishu
mishu

Reputation: 5397

The first problem about your element is the fact that your connectedCallback doesn't "forward" the call to super. That should be the first thing in your method, so it would become:

  connectedCallback() {
    super.connectedCallback();
    this._imageHide();
  }

I am guessing that you just skipped a part from your code and that pageInfo.title is in fact a truthy value. But since I don't know when/how those values are set I am guessing that another issue might be that the _imageHide method runs from the connectedCallback and it might be too early for the tag to be actually stamped into the page.

Unless there's some complexity there about when these values are set, I am guessing you should be fine by simply delaying the call the shortest time possible, but wrapping it in a setTimeout without the second parameter. So in fact connectedCallback would be:

  connectedCallback() {
    super.connectedCallback();
    setTimeout(() => {
      this._imageHide();
    });
  }

And now the third problem would be the fact that the this.$ "shortcut" is not available for elements that are conditionally added into the page. So you should use querySelector, like you said, or maybe getElementById, like:

let image = this.shadowRoot.getElementById('img');

Upvotes: 1

Related Questions