Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
Updated lifecycle callback section. Fixes #1456.
Browse files Browse the repository at this point in the history
Includes changes from #1479.
  • Loading branch information
Arthur Evans committed Jan 21, 2016
1 parent 61f2663 commit 04c70cc
Showing 1 changed file with 132 additions and 46 deletions.
178 changes: 132 additions & 46 deletions 1.0/docs/devguide/registering-elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,17 +177,75 @@ all imports in the document have finished loading.
## Lifecycle callbacks {#lifecycle-callbacks}

Polymer's Base prototype implements the standard Custom Element lifecycle
callbacks to perform tasks necessary for Polymer's built-in features. The hooks
in turn call shorter-named lifecycle methods on your prototype.

- `created` instead of `createdCallback`
- `attached` instead of `attachedCallback`
- `detached` instead of `detachedCallback`
- `attributeChanged` instead of `attributeChangedCallback`
callbacks to perform tasks necessary for Polymer's built-in features.
{{site.project_title}} in turn calls shorter-named lifecycle methods on your
prototype.

Polymer adds an extra callback, `ready`, which is invoked when Polymer has
finished creating and initializing the element's local DOM.

<table>
<tr>
<th>Callback</th>
<th>Description</th>
</tr>
<tr>
<td><code>created</code></td>
<td>Called when the element has been created, but before property values are
set and local DOM is initialized.
<p>Use for one-time set-up before property values are set.
</p>
<p>Use instead of <code>createdCallback</code>.
</p>
</td>
</tr>
<tr>
<td><code>ready</code></td>
<td>Called after property values are set and local DOM is initialized.
<p>Use for one-time configuration of your component after local
DOM is initialized. (For configuration based on property values, it
may be preferable to use an <a href="properties.html#multi-property-observers">observer</a>.)
</p>
</td>
</tr>
<tr>
<td><code>attached</code></td>
<td>Called after the element is attached to the document.
<p>Uses include accessing computed style information, and adding
document-level event listeners. (If you use declarative
event handling, such as <a href="events.html#annotated-listeners">annotated
event listeners</a> or the
<a href="events.html#event-listeners"><code>listeners</code> object</a>,
{{site.project_title}} automatically adds listeners on attach and removes
them on detach.)
</p>

This comment has been minimized.

Copy link
@kaste

kaste Mar 24, 2016

I'm pretty sure that this is not correct. They're added after created and before ready; and they're never removed.

This comment has been minimized.

Copy link
@arthurevans

arthurevans Mar 24, 2016

You are correct. This sentence should either be deleted or rewritten (the point is, you shouldn't need to worry about adding or removing those listeners).

This comment has been minimized.

Copy link
@kaste

kaste Mar 24, 2016

An educated developer should know about event listeners not being removed on detached.

<p>Use instead of <code>attachedCallback</code>.
</p>
</td>
</tr>
<tr>
<td><code>detached</code></td>
<td>Called after the element is attached to the document.
<p>Uses include removing event listeners added in <code>attached</code>.
</p>
<p>Use instead of <code>detachedCallback</code>.
</p>
</td>
</tr>
<tr>
<td><code>attributeChanged</code></td>
<td>Called when one of the element's attributes is changed.
<p>Use to handle attribute changes that <em>don't</em> correspond to
declared properties. (For declared properties, {{site.project_title}}
handles attribute changes automatically as described in
<a href="properties.html#attribute-deserialization">attribute deserialization</a>.)
</p>
<p>Use instead of <code>attributeChangedCallback</code>.
</p>
</td>
</tr>
</table>


Example:

Expand All @@ -199,6 +257,10 @@ Example:
console.log(this.localName + '#' + this.id + ' was created');
},

ready: function() {
console.log(this.localName + '#' + this.id + ' has local DOM initialized');
},

attached: function() {
console.log(this.localName + '#' + this.id + ' was attached');
},
Expand All @@ -214,14 +276,28 @@ Example:

});

<!-- ToDo: the following section should probably be moved to the local DOM chapter. -->

### Ready callback and local DOM initialization {#ready-method}

The `ready` callback is called when an element's local DOM is ready.
The `ready` callback is called when a {{site.project_title}} element's
local DOM has been initialized.

**What is local DOM?** Local DOM is a subtree of elements created and
managed by your element. It's separate from the element's children,
which are called _light DOM_ for clarity. For more information, see
[Local DOM](local-dom.html).
{: .alert .alert-info }

An element is _ready_ when:

* Its property values have been configured, with values data-bound from parents,
deserialized from attribute values, or else set to their default value.

It is called after the element's template has been stamped and all elements
**inside the element's local DOM** have been configured (with values bound from
parents, deserialized attributes, or else default values) and had their `ready`
method called.
* Its local DOM template has been instantiated.

* All of the elements **inside the element's local DOM** are ready, and have had
their `ready` methods called.

Implement `ready` when it's necessary to manipulate an element's
local DOM when the element is constructed.
Expand All @@ -235,36 +311,34 @@ local DOM when the element is constructed.
access a local DOM element.
{: .alert .alert-info }

Within a given tree, `ready` is generally called in _document order_, but you should not
rely on the ordering of initialization callbacks between sibling elements, or between
a host element and its light DOM children.
Within a given tree, `ready` is generally called in _document order_,
but you should not rely on the ordering of initialization callbacks between
sibling elements, or between a host element and its **light DOM** children.

### Initialization order and timing {#initialization-order}

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

- `created` callback
- local DOM initialized (This means that **local DOM** children are created,
their property values are set as specified in the template, and `ready()`
has been called on them)
- `ready` callback
- [`factoryImpl` callback](#custom-constructor) `attached` callback
- `created` callback.
- Local DOM initialized (This means that **local DOM** children are created,
their property values are set as specified in the template, and `ready`
has been called on them).
- `ready` callback.
- [`factoryImpl` callback](#custom-constructor).
- `attached` callback.

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.
elements may vary** depending on many factors, including 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; in general elements are initialized in document order, so children are
usually initialized after their parents. The user can add light children at
any time after the parent element has been defined.
There are no guarantees about the initialization timing of light
DOM children. In general elements are initialized in document order,
so children are usually initialized after their parents.

For example, consider this light DOM for an element `avarar-list` (which would
presumably have, in its local DOM, a `<content>` element with selector on
`.photo`):
For example, consider this light DOM for an element `avatar-list`:

<avatar-list>
<my-photo class="photo" src="one.jpg">First photo</my-photo>
Expand All @@ -274,27 +348,41 @@ presumably have, in its local DOM, a `<content>` element with selector on
`<avatar-list>` is _likely_ to have its `ready` method called before the various
`<my-photo>` elements do.

In addition, the user can add light children at any time after
the parent element has been created. A well-designed element
should handle having its light DOM manipulated at runtime.

To avoid timing issues, you can use the following strategies:

* Handle light DOM children lazily. For example, a popup menu
element may need to count its light DOM children. By counting
its `children` when the menu is opened, it can handle the user
adding and removing menu items with minimal overhead.

* To react when children are added and removed, use the
[`observeNodes` method](local-dom.html#observe-nodes).

#### Initialization timing for local DOM children

In terms of local DOM and initialization timing, Local DOM children are created,
In terms of local DOM and initialization timing, 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.
called on them _before_ their parent's `ready` callback is called.

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 has its `ready` callback called.
* `dom-repeat` and `dom-if` templates create DOM **asynchronously**
after their properties are updated. For example, if you have a
`dom-repeat` in your element's local DOM, the `ready` callback is
invoked before the `dom-repeat` finishes creating its instances.

If you need to know when a `dom-repeat` or `dom-if` creates or
removes template instances, listen for its `dom-change` event.
See [`dom-change` event](templates.html#dom-change) for details.

* Polymer guarantees that local DOM children have their `ready` callback called
before their parent's; however, it cannot guarantee the same thing for the
`attached` callback. This is one fundamental difference between native
behaviour and polyfill behavior.
* Polymer guarantees that local DOM children have their `ready` callback called
before their parent's; however, it cannot guarantee the same thing for the
`attached` callback. This is one fundamental difference between native
behavior and polyfill behavior.

#### Initialization timing for siblings

Expand All @@ -312,14 +400,12 @@ from inside the `attached` callback:
});
}


### Registration callback

`Polymer.Base` also implements `registerCallback`, which is called by `Polymer()`
to allow `Polymer.Base` to supply a [layering system](experimental.html#feature-layering)
for Polymer features.


## Static attributes on host {#host-attributes}

If a custom element needs HTML attributes set on it at create-time, the attributes may
Expand Down

0 comments on commit 04c70cc

Please sign in to comment.