Run a function once all children element are _actually_ updated
Asked Answered
P

1

5

In lit-html we have the firstUpdated() method to run one-time initialisations once an element is rendered.

What if you need to run a function only once all children within that template are updated? And what if your template includes native form elements and custom ones?

Right now I am doing a terrible:

  firstUpdated () {
    super.firstUpdated()

    setTimeout(() => this.onceChildrenAreUpdated(), 100)
  }

Surely there is a better way? I realise it's tricky, because for lit-element "rendered" means that the DOM is done; it doesn't mean that all elements inside have done whichever initialisation then want to do.

But still...

Plasia answered 20/9, 2019 at 23:8 Comment(3)
This sounds like an XY problem. What is the root problem that you're trying to solve?Czar
The containing element needs to run some methods on the contained element. However, those methods only work once the contained elements are fully initialised, which is an async process. This is the X problem.Plasia
I thought that firstupdated only ran after the render was completely finished, but in case that doesn't work, I think you could fire events on every children element's firstupdated and listen to those on the parentGenerable
B
6

You can wait for all the children to be updated:

  async firstUpdated () {
    const children = this.shadowRoot.querySelectorAll('*');
    await Promise.all(Array.from(children).map((c) => c.updateComplete));
    this.onceChildrenAreUpdated();
  }

Replace querySelectorAll('*') with something more specific if possible.

Baillargeon answered 26/9, 2019 at 23:33 Comment(3)
Thanks for answering Justin! I have async _allChildrenCompleted () { // Wait for all children to be ready to rock and roll for (const el of this.elements) { // TODO: What about React, Vue, etc.? Uniform API across element libraries? if (typeof el.updateComplete !== 'undefined') { await el.updateComplete } } }Plasia
Promise.all is meant to be less blocking, but I doubt it will make a meaningful difference for me. But... if the elements I am cycling through are made by other libraries, this won't work. Is there any hope to have a semi-standard API where an element returns true to a promise once it's fully ready to go?Plasia
Unrelated: I would love to hear your comments on this Redux replacement and this example of use with lit-htmlPlasia

© 2022 - 2024 — McMap. All rights reserved.