5

Given the following sample code:

import { LitElement, html, css } from 'lit-element';

class ItemsDisplay extends LitElement {

    static get styles() {...}
    static get properties {...}

    constructor () {
        super();
        ...
    }

    render {
        return html`
            ${this.items.map((item, index, array) => html`
                <div class="name">
                    ...
                </div>
            `)}        
        `;
    }
}

What is the appropriate way to select all nodes with class "name"?

I have tried the following ways, but failed; all times nodesList was undefined:

  • Inside constructor:
  this.nodesList = this.shadowRoot.querySelectorAll(".name");
  • Using:
  firstUpdated(changedProperties) {
      return this.nodesList = this.shadowRoot.querySelectorAll(".name");
  }
  • Inside a custom function:
  getNodesList() {
      let nodesList = this.shadowRoot.querySelectorAll(".name");
      ...
  }

I have also tried with:

connectedCallback() {
    super.connectedCallback();
    return this.nodesList = this.shadowRoot.querySelectorAll(".name");
}

Looking forward reading the solution.

Tia

SONewbiee
  • 363
  • 2
  • 15
  • It will depend on when you call it. You have to make sure that the DOM has be added to `shadowRoot` before the `querySelectorAll` will work. Can you add an example of when you are trying to call it? – Intervalia Feb 25 '19 at 15:34
  • I am trying to call it from `constructor` as `this.getNodesList()`, a function which is placed after `render`. I thought that `lit-element` takes care all necessary work in order a new `element` to be added to the DOM automatically and/or shadowDOM to be added to the shadowRoot!. What do I miss? How can I check within 'lit-element` that shadowRoot is ready for parsing? Tia – SONewbiee Feb 25 '19 at 15:52
  • I have not used lit, but you may need to place your call in a `setTimeout` to allow the browser time to do the actual rendering before the content is really available – Intervalia Feb 25 '19 at 17:02
  • You're not going to be able to query the DOM in the `constructor` and even in `connectedCallback` DOM nodes probably aren't going to be ready yet. What are are you trying to do with the elements and why do you need to query them so early? – abraham Feb 26 '19 at 00:26
  • @Intervalia Tnks for your help. Please also have a look at this [questions](https://stackoverflow.com/questions/54872823/how-to-check-the-initial-render-state-not-the-update-state-of-a-component-in). `setTimeout` will work but it is not the way which will satisfy me! It is an ultimate solution but not an elegant one. A `promise` could be ideal. – SONewbiee Feb 26 '19 at 09:31
  • @abraham Tnks for your help. Please also have a look at this [questions](https://stackoverflow.com/questions/54872823/how-to-check-the-initial-render-state-not-the-update-state-of-a-component-in). When is it **early** or **late**?! Both have to do with the moment of render completion, don't they? I just want to change some attributes of them. – SONewbiee Feb 26 '19 at 09:39
  • @Intervalia `setTimeout` does work. – SONewbiee Feb 26 '19 at 13:13

1 Answers1

6

You shouldn't try to access DOM node in the constructor, because they won't be available yet.

The best place to query DOM nodes is the firstUpdated() lifecycle callback, which is called after the first time your element's DOM has been updated. You also don't need to return it from firstUpdated, you can just do something like:

  firstUpdated(changedProperties) {
    // Store a reference to the form element for easy access
    this.$someNode = this.shadowRoot.querySelector('div');

You can see some examples of this over at: https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F05-querying-dom.js

https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F01-first-updated.js

Additionally, if you're using TypeScript, you can use the query decorator:

@query('div')
myDiv;

More info: https://github.com/Polymer/lit-element/blob/master/src/test/lib/decorators_test.ts#L326

passle
  • 146
  • 2
  • Thnks for your response.I have seen all these examples. I have also used `firstUpdated()` but failed. `changedProperties` is an optional argument in the function or not? In `01-first-updated.js` example, the argument is present but never used/declared. I still read the doc and see the examples over and over again! – SONewbiee Mar 02 '19 at 12:11