Closed mercmobily closed 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.
if
, items
, etc.). Thee 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.ready
is called before parent ready
, 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.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.
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?
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.
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()
?
Correct.
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)
The element's basic initialization order for a given element is:
created
callback ready()
has been called on them) ready
callbackfactoryImpl
callbackattached
callbackNote 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.
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()
.
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:
dom-repeat
and dom-if
create DOM asynchronously based on the property values set on them (e.g. if
, items
, etc.). Note that dom-repeat
isn't a "special" statement: it's a normal 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
.ready
callback called before their parent's; however, it cannot guarantee the same thing for the attached
callback. This is one place where native and polyfill behavior is different.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.
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!
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.
:+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 beforeready
is called on their parent.
:100: this thread is a great read :)
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)
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.
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.
Well I did: #1479 I guess this ticked could/should be closed?
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.
I have a few questions regarding the Initialisation order section.
Here, it looks like the calls above may be called in a different order. However, the next sentence:
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:
So, the order created -> ready -> attached is always observed... whereas factoryImpl and local DOM initialisation may happen anytime?
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:
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:
ready()
before its parent...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!)