Polymer Cheat Sheet
Introduction#
This is a cheat sheet for the Polymer 2.x library. Fork of post from Monica Dinculescu.
Defining an element
Docs: 1.x -> 2.x upgrade guide, registering an element, shared style modules.
<link rel="import" href="bower_components/polymer/polymer-element.html">
<dom-module id="element-name">
<template>
<!-- Use one of these style declarations, but not both -->
<!-- Use this if you don’t want to include a shared style -->
<style></style>
<!-- Use this if you want to include a shared style -->
<style include="some-style-module-name"></style>
</template>
<script>
class MyElement extends Polymer.Element {
static get is() { return 'element-name'; }
// All of these are optional. Only keep the ones you need.
static get properties() { ... }
static get observers() { ... }
}
// Associate the new class with an element name
customElements.define(MyElement.is, MyElement);
</script>
</dom-module>
To get the class definition for a particular custom tag, you can use
customElements.get('element-name')
.
Extending an element
Docs: extending elements, inherited templates.
Instead of Polymer.Element
, a custom element can extend a different element:
class ParentElement extends Polymer.Element {
/* ... */
}
class ChildElement extends ParentElement {
/* ... */
}
To change or add to the parent’s template, override the template
getter:
<dom-module id="child-element">
<template>
<style> /* ... */ </style>
<span>bonus!</span>
</template>
<script>
var childTemplate;
var childTemplate = Polymer.DomModule.import('child-element', 'template');
var parentTemplate = ParentElement.template.cloneNode(true);
// Or however you want to assemble these.
childTemplate.content.insertBefore(parentTemplate.firstChild, parentTemplate);
class ChildElement extends ParentElement {
static get is() { return 'child-element'; }
// Note: the more work you do here, the slower your element is to
// boot up. You should probably do the template assembling once, in a
// static method outside your class (like above).
static get template() {
return childTemplate;
}
}
customElements.define(ChildElement.is, ChildElement);
</script>
</dom-module>
If you don’t know the parent class, you can also use:
class ChildElement extends customElements.get('parent-element') {
/* ... */
}
Defining a mixin
Docs: mixins, hybrid elements.
Defining a class expression mixin to share implementation between different elements:
<script>
MyMixin = function(superClass) {
return class extends superClass {
// Code that you want common to elements.
// If you're going to override a lifecycle method, remember that a) you
// might need to call super but b) it might not exist.
connectedCallback() {
if (super.connectedCallback) {
super.connectedCallback();
}
/* ... */
}
}
}
</script>
Using the mixin in an element definition:
<dom-module id="element-name">
<template><!-- ... --></template>
<script>
// This could also be a sequence:
// class MyElement extends AnotherMixin(MyMixin(Polymer.Element)) { … }
class MyElement extends MyMixin(Polymer.Element) {
static get is() { return 'element-name' }
/* ... */
}
customElements.define(MyElement.is, MyElement);
</script>
</dom-module>
Using hybrid behaviors (defined in the 1.x syntax) as mixins:
<dom-module id="element-name">
<template><!-- ... --></template>
<script>
class MyElement extends Polymer.mixinBehaviors([MyBehavior, MyBehavior2], Polymer.Element) {
static get is() { return 'element-name' }
/* ... */
}
customElements.define('element-name', MyElement);
</script>
</dom-module>
Lifecycle methods
Docs: lifecycle callbacks, ready.
class MyElement extends Polymer.Element {
constructor() { super(); /* ... */ }
ready() { super.ready(); /* ... */ }
connectedCallback() { super.connectedCallback(); /* ... */ }
disconnectedCallback() { super.disconnectedCallback(); /* ... */ }
attributeChangedCallback() { super.attributeChangedCallback(); /* ... */ }
}
Data binding
Docs: data binding, attribute binding, binding to array items, computed bindings.
Don’t forget: Polymer camel-cases properties, so if in JavaScript you use myProperty
,
in HTML you would use my-property
.
One way binding: when myProperty
changes, theirProperty
gets updated:
<some-element their-property="[[myProperty]]"></some-element>
Two way binding: when myProperty
changes, theirProperty
gets updated,
and vice versa:
<some-element their-property="{{myProperty}}"></some-element>
Attribute binding: when myProperty
is true
, the element is hidden; when it’s
false
, the element is visible. The difference between attribute and property
binding is that property binding is equivalent to someElement.someProp = value
,
whereas attribute binding is equivalent to: someElement.setAttribute(someProp, value)
<some-element hidden$="[[myProperty]]"></some-element>
Computed binding: binding to the class
attribute will recompile styles when
myProperty
changes:
<some-element class$="[[_computeSomething(myProperty)]]"></some-element>
<script>
_computeSomething: function(prop) {
return prop ? 'a-class-name' : 'another-class-name';
}
</script>
Observers
Docs: observers, multi-property observers, observing array mutations, adding observers dynamically.
Adding an observer
in the properties
block lets you observe changes in the
value of a property:
static get properties() {
return {
myProperty: {
observer: '_myPropertyChanged'
}
}
}
// The second argument is optional, and gives you the
// previous value of the property, before the update:
_myPropertyChanged(value, /*oldValue */) { /* ... */ }
In the observers
block:
static get observers() {
return [
'_doSomething(myProperty)',
'_multiPropertyObserver(myProperty, anotherProperty)',
'_observerForASubProperty(user.name)',
// Below, items can be an array or an object:
'_observerForABunchOfSubPaths(items.*)'
]
}
Adding an observer dynamically for a property otherProperty
:
// Define a method.
_otherPropertyChanged(value) { /* ... */ }
// Call it when `otherPropety` changes.
this._createPropertyObserver('otherProperty', '_otherPropertyChanged', true);