Polymer 2.0 is designed to support the new custom elements v1 and shadow DOM v1 specifications being implemented by most major browser vendors, while providing a smooth migration path for Polymer 1.x users.
Polymer 2.0 also makes improvements in several areas:
-
Improved interoperability. By removing the need to use Polymer.dom for DOM manipulation, Polymer 2.0 makes it easier to use Polymer components with other libraries and frameworks. In addition, the shady DOM code has been separated out into a reusable polyfill, instead of being integrated into Polymer.
-
Data system improvements. Polymer 2.0 includes targeted improvements to the data system. These changes make it easier to reason about and debug the propagation of data through and between elements.
-
More standard. Polymer 2.0 uses standard ES6 classes and the standard custom elements v1 methods for defining elements, instead of a Polymer factory method. You can mix in features using standard JavaScript (class expression mixins) instead of
Polymer
behaviors. (ThePolymer
factory method is still supported using a compatibility layer.)
Some tests currently fail on non-Chrome browsers; these will be addressed soon, but in the short term Chrome Canary is your best bet.
Polymer 2.0 introduces a number of breaking changes—many of which are required by new custom elements v1 and shadow DOM v1 specifications. Expect to see more changes as this new version nears release.
The following sections describes the major changes in Polymer 2.0. For details on upgrading elements to Polymer 2.0, see the upgrade guide.
Custom elements v1
Polymer 2.0 elements target the custom elements v1 API, which makes several changes to the v0 version of the spec used in Polymer 1.x. In particular:
-
The custom elements v1 spec defines elements using ES6 classes, instead of prototypes.
Polymer 2.0 lets you use this native ES6 form by providing an ES6 base class (
Polymer.Element
) for your elements to extend. In addition, legacy elements using thePolymer
factory method are supported with a Polymer 1.x compatibility layer. -
The new spec has some changes to the lifecycle callbacks. In particular, instead of a created callback it invokes the class constructor. The spec also imposes new restrictions on what can be done in the constructor (equivalent to the
created
callback in Polymer 1.x). -
In addition, although they are supported in the specification, Polymer 2.0 does not currently support type-extension elements (
is=
). -
Because of complications related to the new specification, the
disable-upgrade
feature is not supported in 2.x. It may be added later as a mixin or add-on.
The following sections describe these changes in more detail.
For general information on the custom elements v1 specification, see Custom elements v1: reusable web components on Web Fundamentals.
Lifecycle changes
When creating class-based elements, use the new native lifecycle methods (called "custom element
reactions"). When creating legacy elements using the Polymer
factory method, use the legacy Polymer
callback names.
Reaction/callback name | Notes |
constructor ( native)
|
The custom elements v1 spec forbids reading attributes, children, or parent information from
the DOM API in the constructor (created callback in the legacy API).
Likewise, attributes and children may not be added in the constructor . Any such
work must be deferred (for example, until connectedCallback ).
The legacy
However, you can now set any property defaults within the |
connectedCallback ( native)
|
Polymer 1.x deferred the attached callback until after first render, so elements
could measure themselves or their children.
|
disconnectedCallback ( native)
|
|
attributeChangedCallback ( native)
|
Attributes must be explicitly registered to be observed.
For Polymer elements, only properties explicitly declared in the
In custom elements v0, the
In Polymer 1.x, attributes were deserialized for both explicitly declared properties and
implicitly declared properties. For example, a property used in a binding or as the
dependency of an observer, but not declared in |
ready (Polymer specific)
|
Polymer no longer guarantees that the initial light DOM distribution is complete before ready is called. |
In addition to changes in the callbacks, note that the lazyRegister
option has been removed and
all meta-programming (parsing the template, creating accessors on the prototype, and so on) is
deferred until the first instance of the element is created.
Type-extension elements
Polymer 2.0 doesn't support type-extension elements (for example, <input is="iron-input">
).
Type-extension support is still included in the custom elements v1 spec (as "customized built-in
elements"), and scheduled for implementation in Chrome. However, since Apple has said it will not
implement is
, we will not be encouraging its use to avoid indefinite reliance on the custom
elements polyfill. Instead, a wrapper custom element can surround a native element. For example:
<a is="my-anchor">...</a>
Could become:
<my-anchor>
<a>...</a>
</my-anchor>
Users will need to change existing type-extension elements where necessary.
All template type extensions provided by Polymer (i.e. dom-if
and dom-repeat
) now have a corresponding standard custom element
that includes a <template>
in its light DOM. For example:
If in 1.x, code reads:
<template is="dom-bind">...</template>
In 2.x, it becomes:
<dom-bind>
<template>...</template>
</dom-bind>
Polymer automatically wraps template type extensions used in Polymer element templates (i.e. inside a dom-module
) during template
processing. This means you can and should continue using <template is="">
in templates nested
inside a Polymer element, or another Polymer template, such as dom-bind
.
Templates used in the main document, such as index.html
must be manually wrapped.
The custom-style
element has also been changed to a standard custom element that must wrap a
<style>
element. For example:
<style is="custom-style">...</style>
Becomes:
<custom-style>
<style>...</style>
</custom-style>
References:
- Creating a customized built-in element in the WHATWG HTML specification.
- Apple's position on customized built-in elements.
Shadow DOM v1
Polymer 2.0 supports shadow DOM v1. For Polymer users, the main differences in v1 involve replacing
<content>
elements with v1 <slot>
element.
The shady DOM shim that was part of Polymer 1.x has been factored out of Polymer and added to the
webcomponents-lite.js
polyfill bundle, along with the related shim for CSS Custom Properties.
This new version of shady DOM no longer exposes an alternative (Polymer.dom
) API but instead
patches the native DOM API, so 2.0 users can use the native DOM APIS directly.
For hybrid elements, Polymer 2.0 includes a version the Polymer.dom
API that forwards directly to
the native API. For 2.0-only elements, Polymer.dom
can be eliminated in favor of the native DOM
APIs.
Read more on Web Fundamentals. For an overview of shadow DOM, see Shadow DOM v1: self-contained web components on Web Fundamentals.
For a brief but comprehensive set of examples illustrating the shadow DOM v1 spec changes, see What's New in Shadow DOM v1 (by examples) by Hayato Ito.
Data system improvements
Polymer 2.0 introduces a number of improvements in the data system:
-
Simpler array handling. Eliminates the
Polymer.Collection
abstraction and key-based paths for array items. -
Batched data changes, which can improve performance as well as correctness.
-
Undefined dependency checks for observers, computed bindings and computed properties have been removed. These are all called once at initialization time.
-
An optional element mixin that eliminates dirty checking for objects or arrays. This means that when you make an observable change to an object or array property, Polymer re-evaluates everything below that property (sub-properties, array items). This can be useful for applications that can't use the Polymer
set
and array mutation methods, and do not use immutable data patterns. -
Change in property effect order.
-
Only properties listed explicitly in
properties
can be configured from an attribute. -
Element initialization (including template stamping and data system initialization) is deferred until the element is connected to the main document. (This is a result of the custom element v1 changes.)
-
Several miscellaneous smaller changes.
The following sections describe these changes in more detail.
Dirty checking for objects and arrays
Polymer 1.x uses a dirty-checking mechanism to prevent the data system from doing extra work. Polymer 2.x retains this mechanism by default, but lets elements opt out of dirty checking objects and arrays.
With the default dirty-checking mechanism, the following code doesn't generate any property effects:
this.property.subproperty = 'new value!';
this.notifyPath('property');
Because property
still points to the same object, the dirty check fails, and sub-property changes
don't get propagated. Instead, you need to use the Polymer set
or array mutation methods, or
call notifyPath
on the exact path that changed:
this.set('property.subproperty', 'new value!');
// OR
this.property.subproperty = 'new value!';
this.notifyPath('property.subproperty');
In general, the dirty-checking mechanism is more performant. It works for apps where one of the following is true:
- You use immutable data.
- You always use the Polymer data mutation methods to make granular changes.
However, for apps that don't use immutable data and can't use the Polymer data methods, Polymer 2.0
provides an optional MutableData
mixin. The MutableData
mixin eliminates the dirty check, so the code above would work as intended. This also lets you batch several changes
before invoking property effects:
this.property.arrayProperty.push({ name: 'Alice' });
this.property.stringProperty = 'new value!';
this.property.counter++;
this.notifyPath('property');
You can also use set or simply set a top-level property to invoke effects:
this.set('property', this.property);
// or
this.property = this.property;
Using set
to change a specific subproperty can often be the most efficient way to make changes.
However, elements that use MutableData
shouldn't need to use this API, making it
more compatible with alternate data-binding and state management libraries.
Note that when you re-set a property at the top-level, all property effects for that property and
its subproperties, array items, and so-on are re-run. Observers with wildcard paths (like prop.*
)
are only notified with the top-level change:
// 'property.*' observers fire with the path 'property'
this.property.deep.path = 'another new value';
this.notifyPath('property');
Using set
to set specific paths generates granular notifications:
// 'property.*' observers fire with the path 'property.deep.path'
this.set('property.deep.path', 'new value');
Simpler array handling
The Polymer.Collection
API and its associated key-based path and splice notification for arrays
has been eliminated.
There are several other benefits to this change:
- Arrays of primitive values are supported.
- Array items don't need to be unique.
Since key paths have been eliminated, array splice notifications only include the indexSplices
property, not keySplices
.
Batched data changes
Propagation of data through the binding system is now batched, such that complex observers and computing functions run once with a set of coherent changes. There's two ways to create a set of coherent changes:
-
An element automatically creates a set of coherent changes when it initializes its properties.
-
You can programmatically create a set of coherent changes using the new
setProperties
method.
this.setProperties({ item: 'Orange', count: 12 });
Single property accessors still propagate data synchronously. For example, given an observer that
observes two properties, a
and b
:
// observer fires twice
this.a = 10;
this.b = 20;
// observer fires once
this.setProperties({a: 10, b: 20});
Property effect order
In 2.0, observers fire before property-change notifications. The effect order in 2.0 is:
- Recompute computed properties.
- Propagate values to data bindings.
- Reflect properties to attributes.
- Run observers.
- Fire property-change notifications.
In 1.x, observers fire last, after property-change notifications.
Observer changes
In 2.x, the checks preventing observers from firing with undefined dependencies are removed.
Specifically:
-
Multi-property observers, computed properties, and computed bindings run once at initialization if any dependencies are defined, and for each change thereafter.
-
The observer or computing functions may now receive
undefined
as an argument value, and needs to handle it correctly.
2.x also adds the ability to define observers and computed properties dynamically, on a per-instance basis. For details, see Add observers and computed properties dynamically.
Miscellaneous data system changes
-
Setting/changing any function used in a computed binding causes the binding to re-compute its value using the new function and current property values. For example, given the binding:
some-property="{{_computeValue(a, b)}}"
Changing the
_computeValue
function causes the binding to be re-evaluated, even ifa
andb
remain the same:this._computeValue = function(a, b) { ... }
-
Property change notifications (
property-changed
events) aren't fired when the value changes as a result of a binding from the host.
- In order for a property to be deserialized from its attribute, it must be declared in the
properties
metadata object. In Polymer 1.x, deserialization is also done for properties that are implicitly declared (for example, by being included in a binding or as an observer dependency).
Polymer 1 compatibility layer
Polymer 2.0 retains the existing polymer/polymer.html
import that current Polymer 1.0 users can
continue to import. This import includes the legacy Polymer function for defining elements, and
strives to provide a very minimally-breaking change for code written to the Polymer 1.0 API.
For the most part, existing users upgrading to Polymer 2.0 will only need to adapt existing code to be compliant with the shadow DOM v1 API related to content distribution and styling, as well as minor breaking changes introduced due to changes in the custom elements v1 API.
Removed methods and properties
In keeping with a goal of reducing unnecessary code, the new ES6 base element, Polymer.Element
,
leaves out a number of methods and properties. The removed APIs fall into several categories:
- Simple sugaring for native DOM APIs. For example
fire
andtransform
. - Rarely-used attributes and properties, like
attributeFollows
andclassFollows
. - Methods and properties that don't belong on the instance. For example, in 1.x
importHref
was an instance method, but it doesn't do anything instance-specific, except for binding the callback.
A comprehensive list of missing or moved APIs will be available after the API for Polymer.Element
is finalized.
Browser support and polyfills
When released, Polymer 2.0 should support the same set of browsers as Polymer 1.x—IE 11, Edge, Safari (9+), Chrome, Opera and Firefox.
Polymer 2.0 has been developed alongside and tested with a new suite of v1-spec compatible polyfills
for custom elements and shadow DOM. You can test Polymer 2.0 by using a webcomponentsjs
version
greater or equal to 1.0.0
, which is included as a bower dependency to Polymer 2.x.
There are several ways to load the polyfills:
webcomponents-lite.js
includes all of the polyfills necessary to run on any of the supported browsers.webcomponents-loader.js
performs a runtime feature-detection and loads just the required polyfills.
Read more about the different ways and their tradeoffs:
EcmaScript 2015 (a.k.a. ES6)
Polymer 2.x and 2.x class-style elements are written using the next generation of the JavaScript standard, EcmaScript 2015 (more commonly known as ES6). This is required by the new custom element specification. If you're not familiar with ES6, it would be helpful to familiarize yourself with the basics of ES6 as used by Polymer. In particular, the following features are used widely in the code examples:
There are a number of learning resources available on the web, including:
ES6 can be run without compilation in current Chrome, Safari 10, Safari Technology Preview, Firefox, and Edge. Compilation is required to run Polymer 2.x in IE11 and Safari 9.
The Polymer CLI and polymer-build
library support transpiling ES6 to ES5 at build time. In
addition, the polymer serve
and polymer test
commands transpile as runtime when required by the
browser.
For more information, see Browser compatibility.
Install Polymer 2.0
You can install the latest Polymer 2.x release using bower:
bower install --save Polymer/polymer#^2.0.0
You can also use bower to install any of the available hybrid elements:
bower install --save PolymerElements/paper-button#^2.0.0
Upgrade an existing project
See the upgrade guide for information on getting your code working with 2.0.
Polymer element availability
The team is in the process of updating the Polymer elements to use the new "hybrid" format compatible with both Polymer 1.7+ and 2.x.
The following elements have been updated to support Polymer 2.0, or require no updates:
- app-layout
- app-localize-behavior
- app-pouchdb
- app-route
- app-storage
- gold-zip-input
- iron-a11y-announcer
- iron-a11y-keys
- iron-a11y-keys-behavior
- iron-ajax
- iron-autogrow-textarea
- iron-behaviors
- iron-checked-element-behavior
- iron-collapse
- iron-component-page
- iron-demo-helpers
- iron-doc-viewer
- iron-dropdown
- iron-fit-behavior
- iron-flex-layout
- iron-form-element-behavior
- iron-icon
- iron-icons
- iron-iconset
- iron-iconset-svg
- iron-image
- iron-input
- iron-jsonp-library
- iron-label
- iron-list
- iron-localstorage
- iron-location
- iron-media-query
- iron-menu-behavior
- iron-meta
- iron-overlay-behavior
- iron-pages
- iron-range-behavior
- iron-resizable-behavior
- iron-scroll-target-behavior
- iron-scroll-threshold
- iron-selector
- iron-test-helpers
- iron-validatable-behavior
- iron-validator-behavior
- marked-element
- neon-animation
- paper-badge
- paper-behaviors
- paper-button
- paper-card
- paper-checkbox
- paper-dialog
- paper-dialog-behavior
- paper-dialog-scrollable
- paper-drawer-panel
- paper-dropdown-menu
- paper-fab
- paper-header-panel
- paper-icon-button
- paper-input
- paper-item
- paper-listbox
- paper-material
- paper-menu-button
- paper-progress
- paper-radio-button
- paper-radio-group
- paper-ripple
- paper-scroll-header-panel
- paper-slider
- paper-spinner
- paper-styles
- paper-swatch-picker
- paper-tabs
- paper-toast
- paper-toggle-button
- paper-toolbar
- paper-tooltip
- platinum-sw
- polymerfire
- polymerlabs/note-app-elements
- prism-element