javascriptlit

LitElement and until directive - How to get called back when result from until is rendered?


I am using LitElement and the until directive. Assume I am loading some data from the server. When this data is available, i want to render the data. And assume i am rendering some element where, for whatever reason, i need to get the DOM reference to manipulate it or call a method. Normally, this can be done with the firstUpdated or updated callbacks on the element. But with the until directive in between, I am not sure how to get called back after the until had rendered. See my code below:

import { LitElement, css, html } from "lit";
import { until } from "lit/directives/until.js";

export class MyComponent extends LitElement {
  static properties = {};

  connectedCallback() {
    super.connectedCallback();
  }

  render() {
    return html`
      ${until(
        this.fetchData(),
        html`
          loading....
        `
      )}
    `;
  }

  async fetchData() {
    return html`
      <div id="elem">Element loaded</div>
    `;
  }

  updated() {
    console.log("Trying to access div: " + document.querySelector("#elem"));
  }
}

customElements.define("my-component", MyComponent);

https://codepen.io/38leinaD/pen/GRzQVoE

This always prints Trying to access div: null. Without the until, it would work. What is the right way to get called back after the elements in the until are rendered?

Thanks, Daniel

UPDATE: When i copied the reproducer from my real project, i forgot about the shadowRoot. Because in the actual project i am not using the shadowDom. So, that part is not the point of my question. So, Chellappan in his answer is right about that. But the main part of the question is about updated and updateCompleted. Why do I need both to make it work?


Solution

  • To access an element within the Shadow DOM, use this.shadowRoot, which refers to the root node of the Shadow DOM of the current web component.

    It's important to wait for the component's update cycle to complete before attempting to access its elements. This can be accomplished using the updateComplete promise.

    updated() {
        this.updateComplete.then(()=>{
             console.log("Trying to access div: ",this.shadowRoot.querySelector('#elem'));
        });
      }