Max888
Max888

Reputation: 3760

LitElement wont set textContent for native Web Component

I have built a native web component called <expanding-textarea> which extends the functionality of <textarea>. I am able to set text content of the component like <expanding-textarea>content goes here</expanding-textarea> but not when I try to set the content dynamically by using the component within a LitElement. The below is a minimal example which populates the text correctly for <textarea>${item.text}</textarea> within the repeat directive, but not as is.

<body>
  <my-element></my-element>
  <script type="module">
    const template = document.createElement("template");
    template.innerHTML = `<textarea></textarea>`;
    class ExpandingTextarea extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({ mode: "open" });
        this.shadowRoot.appendChild(template.content.cloneNode(true));
        const textarea = this.shadowRoot.querySelector("textarea");
        textarea.textContent = this.textContent;
      }
    }
    customElements.define("expanding-textarea", ExpandingTextarea);

    import { LitElement, html } from "lit-element";
    import { repeat } from "lit-html/directives/repeat.js";
    class MyElement extends LitElement {
      static get properties() {
        return {
          list: { type: Array },
        };
      }
      constructor() {
        super();
        this.list = [
          { id: "1", text: "hello" },
          { id: "2", text: "hi" },
          { id: "3", text: "cool" },
        ];
      }
      render() {
        return html`
          ${repeat(
            this.list,
            item => item.id,
            item => html`<expanding-textarea>${item.text}</expanding-textarea>`
          )}
        `;
      }
    }
    customElements.define("my-element", MyElement);
  </script>
</body>

Upvotes: 3

Views: 900

Answers (1)

Thad
Thad

Reputation: 975

The problem is that this.textContent has no value in the constructor() because <expanding-textarea> is not yet in the DOM. this.textContent will have value only after <expanding-textarea> is connected to the DOM. So change ExpandingTextarea to

class ExpandingTextarea extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.appendChild(template.content.cloneNode(true));
  }
  connectedCallback() {
    const textarea = this.shadowRoot.querySelector("textarea");
    textarea.textContent = this.textContent;
  }
}

You can see this on Stackblitz (https://stackblitz.com/edit/expanding-textarea?file=my-element.js)

Upvotes: 2

Related Questions