4

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...

Merc
  • 16,277
  • 18
  • 79
  • 122
  • This sounds like an [XY problem](https://meta.stackexchange.com/a/66378). What is the root problem that you're trying to solve? – Jordan Running Sep 23 '19 at 21:31
  • 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. – Merc Sep 24 '19 at 22:02
  • 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 parent – Alan Dávalos Sep 25 '19 at 02:39

1 Answers1

5

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.

Justin Fagnani
  • 10,483
  • 2
  • 27
  • 37
  • 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 } } } – Merc Oct 15 '19 at 03:41
  • 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? – Merc Oct 15 '19 at 03:44
  • Unrelated: I would love to hear your comments on this [Redux replacement](https://github.com/mobily-enterprises/reducs/blob/master/reducs.js) and this [example of use with lit-html](https://glitch.com/edit/#!/lacy-ornament) – Merc Oct 28 '19 at 04:06