Polymer / old-docs-site

Old Polymer site. Replaced by these repos: polymer-project.org, polymer-library-docs
https://www.polymer-project.org
1.02k stars 2.44k forks source link

Several questions about the "Initialisation order" section #1456

Closed mercmobily closed 8 years ago

mercmobily commented 8 years ago

I have a few questions regarding the Initialisation order section.

The element’s basic initialization order is: created callback local DOM initialized ready callback factoryImpl callback attached callback

  • What do you mean by "local DOM initialised"? Is it when various helpers (dom-repeat, etc) are set? Or all elements in the local DOM are ready()ed? Or... what do you mean exactly?

Note that the initialization order may vary depending on whether or not the browser includes native support for web components.

Here, it looks like the calls above may be called in a different order. However, the next sentence:

In particular, there are no guarantees with regard to initialization timing between sibling elements or between parents and light DOM children.

Seems to focus on initialisation timing among parent/siblings, rather than initialisation order within an element. And it's talking specifically about light DOM...

The document then continues:

The created callback is always called before ready. The ready callback is always called before attached.

So, the order created -> ready -> attached is always observed... whereas factoryImpl and local DOM initialisation may happen anytime?

The ready callback is called on any local DOM children before it’s called on the host element.

Does that mean that ready() is called on the host element before any local DOM children, but you cannot trust the light DOM children's ready() to be called after the host element's ready()?

Finally, the doc says:

For accessing sibling elements when an element initializes, you can call async from inside the attached callback:

Does that mean siblings within the light DOM? Or local DOM? Or either?

OK, I must admit I am totally confused by this section. Help :D

The main points are:

I would do the following:

I am sorry, this ticket is confusing because I really haven't managed to make heads or tails of what exactly the issues are.

In the Migration guide, I read:

"A more complete solution is in progress. In the meantime, if you are using domReady in 1.0 you can replace it by using the async method inside your attached callback:"

Is there a ticket where this is being tackled? I'd love to have a look.

Sorry, as you can see I am going through the Polymer documentation, and... I guess that's what you get when you get somebody ever so slightly obsessive to go through things...

(Plus, it's not clear how an element would be able to know when all of its light DOM children are fully initialised!)

arthurevans commented 8 years ago

No apologies necessary, keep up the great feedback.

The section is confusing partly because there are only a few guarantees we can give, and many mysteries. But your feedback is spot-on and we can definitely clarify many of these points.

Broadly speaking, your interpretation is correct as I understand it.

For any given element, the order is as listed.

Local DOM init means, "local DOM children are created, their property values are set as specified in the template, and ready() has been called on them." In essence, it means, "the stuff we do before calling ready," so maybe we can just be clearer about what that is and drop it from this list.

As for light children, there are no guarantees at all, although broadly speaking you would expect them to be ready in document order, which means they'd be initialized after their parents. Usually. Of course, the user can add light children at any time.

Fortunately, you can now use observeNodes if you need to track light DOM nodes. We should add a cross-reference here because it's a common question with regard to lifecycle.

mercmobily commented 8 years ago

When you say:

Caveat 1: dom-repeat and dom-if create dom asynchronously based on the property values you set on them (if, items, etc.). These elements can't start rendering (i.e., creating DOM) until ready has been called on them, so this DOM isn't going to be complete when ready is called on the parent element.

Here, what do you mean by "These", and what do you mean by "them"? So, this means that an element will have ready() called before the dom-repeat has actually gone through everything. Right?

We guarantee that local DOM child ready is called before parent ready,

(Except for elements created in a dom-repeat statement!)

but we can't guarantee the relative ordering of local DOM child attached and parent attached. This is one place where native and polyfill behavior is different.

Meaning that the an element E with children elements C1 C2 C3 might be attached to its parent P before C1, C2 and C3 are attached to E itself?

arthurevans commented 8 years ago

For #1, by "these elements" and "them" I mean "dom-if or dom-repeat elements".

The thing to remember is that the dom-repeat isn't some kind of special statement, it's a custom element. When you set an items value on it, it responds by asynchronously creating instances of its template contents. When you use it inside an element's template, the parent element instantiates a dom-repeat element, sets its items property, and calls ready on it--at that point, the dom-repeat starts its own (async) work, while the parent element goes on getting ready.

On the last comment--I'm not sure whether the actual attachment happens in a different order, or just the attached callback. We actually defer firing attached on any given element until after it's ready. So, there may be a period where the browser thinks the element is attached, but the element hasn't had its attached callback called yet.

mercmobily commented 8 years ago

And about this one:

As for light children, there are no guarantees at all, although broadly speaking you would expect them to be ready in document order, which means they'd be initialized after their parents. Usually. Of course, the user can add light children at any time.

So if I have something like that:

<avatar-list>
  <my-photo class="photo" src="one.jpg">First photo</my-photo>
  <my-photo class="photo" sec="two.jpg">Second photo</my-photo>
</avatar-list>

And avatar-list has <content> element with selector on .photo somewhere, <avatar-list> is likely to be ready() before the various <my-photo> elements are ready()?

arthurevans commented 8 years ago

Correct.

mercmobily commented 8 years ago

My attempt to amend the existing documentation. I tried to integrate everything we discussed, so that (hopefully) nobody wonders the same thing.

I divided the issue in three different parts; I feel that this makes things clearer. I also made a distinction between initialisation order and initialisation timing.

I would love to also have a section here that explains the practical implications of this. When does it really matter than a child's ready() hasn't yet been called?

(Note that I tried my best to use american spellings, but UK/Aussie slip-ups might have happened :D (I'm Australian)


Initialization order and timing {#initialization-order}

The element's basic initialization order for a given element is:

Note that while the life cycle callbacks listed above will be called in the described order for any given element, the initialization timing between elements may vary depending on whether or not the browser includes native support for web components.

Initialization timing for light DOM children

As far as initialization timing of light DOM children there are no guarantees at all, although broadly speaking you would expect them to be ready in document order, which means they'd be usually initialized after their parents. Of course, the user can add light children at any time.

For example if you have something like this:

<avatar-list>
  <my-photo class="photo" src="one.jpg">First photo</my-photo>
  <my-photo class="photo" src="two.jpg">Second photo</my-photo>
</avatar-list>

And avatar-list has a <content> element with selector on .photo, <avatar-list> is likely to be ready() before the various <my-photo> elements are ready().

Initialization timing for local DOM children

Local DOM children are created, their property values are set as specified in the template, and ready is called on them before their parent's ready is.

There are two caveats:

Initialization timing for siblings

There are no guarantees with regard to initialization timing between sibling elements.

This means that siblings may become ready in any order.

For accessing sibling elements when an element initializes, you can call async from inside the attached callback:

attached: function() {
   this.async(function() {
      // access sibling or parent elements here
   });
}

I hope this helps...

Merc.

mercmobily commented 8 years ago

BTW I realise what I wrote is longer than the original version. As usual, if you think it's not up to standard or not usable, 10000% NOT hard feelings!

arthurevans commented 8 years ago

Thanks Merc. I think I can use something like that, but I'd have to massage to fit the doc site style.

If you're interested, you can open a PR and I'll walk you through the edits. Or I can do it.

BLamy commented 8 years ago

:+1: This new explanation actually helped me quite a bit.

You may want to change

Local DOM children are created, their property values are set as specified in the template, and ready is called on them before their parent's ready is.

to something which gives a brief ELI5 explanation of what local dom is, and then get into how it behaves.

Local DOM refers to the children which are located in the template inside of your dom-module. Local DOM children are created, their property values are set, and ready is called on them before ready is called on their parent.

robdodson commented 8 years ago

:100: this thread is a great read :)

mercmobily commented 8 years ago

Sorry for answering so late. My computer actually broke, and had to real with some interesting disaster recovery... I cloned the "docs" repo, and managed to serve it locally. Shall I just fix the explanation I wrote (I have already found a couple of mistakes), patch the relevant file, and summit a PR? (If you think my explanation deserves to be on the docs -- if not, all good, honestly)

arthurevans commented 8 years ago

Hi @mercmobily! Sorry to hear about your computer.

I think the general structure is good, we need to make the language a little less chatty, but that's a detail. If you're up for it, please go ahead with the PR!

I'm off work until the new year, so if you don't hear from me right away... I'm not neglecting you, but this eggnog's not going to drink itself.

mercmobily commented 8 years ago

Hi,

OK will do!

Merc. ᐧ

On 24 December 2015 at 04:17, Arthur Evans notifications@github.com wrote:

Hi @mercmobily https://github.com/mercmobily! Sorry to hear about your computer.

I think the general structure is good, we need to make the language a little less chatty, but that's a detail. If you're up for it, please go ahead with the PR!

I'm off work until the new year, so if you don't hear from me right away... I'm not neglecting you, but this eggnog's not going to drink itself.

— Reply to this email directly or view it on GitHub https://github.com/Polymer/docs/issues/1456#issuecomment-166983328.

mercmobily commented 8 years ago

Well I did: #1479 I guess this ticked could/should be closed?

dwsmorris commented 8 years ago

Hi,

I'm looking for a way to ensure that the attached callback on child elements are called before the attached callback on the parent. I have initialization logic in 'attached' that requires that this be true. A related suggestion above for using async does actually work, in that, if you wrap the parent's attached code in async, it is called after the childs. However, this only works for components two levels deep. If I have a component three levels deep, I can't guarantee the order in which the attached callbacks are called by using async. Is there a way to do this? I can't use ready as I need to be able to reference the local dom.

Thanks, Darryl


update: So, I found a way to do this in "ready" which has order guaranteed (probably doing initialization-sensitive work in attached was wrong anyway). I can fish out the correct nodes in "ready" using this.$ (rather than document.querySelector that I was doing in "attached"). I now need to id the nodes but that's no biggie.