Being a typical aspect of Object Oriented Design, inheritance, and mixins, provide the means by which modular reuse patterns can be facilitated within a given system. Similarly, Polymer facilitates code reuse patterns by employing the notion of shared behaviors modules. Let’s take a quick look at how to leverage them in Polymer when using ES6 classes.
Implementing Behaviors
Implementing a Behavior is quite simple, just define an object within a block expression or an IIFE, and expose it via a namespace, or module loader of choice:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 'use strict'; (() => { // define the behavior const SomeBehavior = { ... }; // add the behavior to a specific namespace ... const ns = (window.SomeNamespace = window.SomeNamespace || {}); ns.SomeBehavior = SomeBehavior; })(); |
some-behaviors.js
Then, include the behavior in a corresponding .html document of the same name so as to allow the behavior to be imported by subsequent elements:
1 2 3 | <script src="some-behaviors.js" type="text/javascript"></script> |
some-behavior.html
Extending Behaviors
After having defined and exposed a given Behavior, the Behavior can then be extended from element classes by defining a behaviors getter / setter
as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 'use strict'; // define element class ... class SomeElement { beforeRegister(){ this.is = 'some-element'; } // implement behaviors getter, returning an array of behaviors // which are to be extended ... get behaviors() { return [window.SomeNamespace.SomeBehavior] } // implement corresponding setter ... set behaviors(val) { this._behaviors = val; } } |
Once the behavior has been extended, simply import the behavior in the element’s template (or element bundle, etc.) and it is available to the template class:
1 2 3 4 5 6 7 8 9 10 | <!-- import behavior module --> <link rel="import" href="some-behavior.html"> <dom-module id="some-element"> <template> ... </template> <script src="some-element.js" type="text/javascript"></script> </dom-module> |
Implementing Multiple Behaviors
Similar to individual behaviors, multiple behaviors can also be defined and extended:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 'use strict'; (() => { // define first behavior ... const FirstBehavior = { properties: { first: { type: String, value: 'First Behavior' } } }; // add the behaviors to the given namespace ... const ns = (window.SomeNamespace = window.SomeNamespace || {}); ns.FirstBehavior = FirstBehavior; })(); |
first-behavior.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 'use strict'; (() => { // define second behavior ... const SecondBehavior = { properties: { second: { type: String, value: 'Second Behavior' } } }; // add the behaviors to the given namespace ... const ns = (window.SomeNamespace = window.SomeNamespace || {}); ns.SecondBehavior = SecondBehavior; })(); |
second-behavior.js
In certain cases, I have found it helpful to group related behaviors together within a new behaviors (array) which bundles the individual behaviors together:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 'use strict'; (() => { // define first behavior ... const FirstBehavior = { properties: { first: { type: String, value: 'First Behavior' } } }; // define second behavior ... const SecondBehavior = { properties: { second: { type: String, value: 'Second Behavior' } } }; // define third behavior ... const ThirdBehavior = { properties: { third: { type: String, value: 'Third Behavior' } } }; // define a behavior which bundles the related behaviors ... const FourthBehavior = [ FirstBehavior, SecondBehavior, ThirdBehavior ]; // add the behaviors to a specific namespace ... const ns = (window.SomeNamespace = window.SomeNamespace || { 'FirstBehavior' : FirstBehavior, 'SecondBehavior' : SecondBehavior, 'ThirdBehavior' : ThirdBehavior, 'FourthBehavior' : FourthBehavior }); })(); |
Note: As can be seen in the FourthBehavior, a behavior can also be implemented as an Array of previously defined behaviors.
Extending Multiple Behaviors
As with extending individual behaviors, multiple behaviors can also be extended using a behaviors getter / setter
. However, when extending multiple behaviors in ES6, there are syntactic differences which one must take note of. Specifically, the behaviors getter
must be implemented as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // define element class ... class CustomElement { beforeRegister(){ this.is = 'custom-element'; } // implement behaviors getter, returning an array of behaviors // which are to be extended via this._behaviors, or, assigning // and returning the array of behaviors to be extended should // this._behaviors be undefined ... get behaviors() { const ns = window.SomeNamespace || {}; return this._behaviors || (this._behaviors = [ ns.FirstBehavior, ns.SecondBehavior, ns.ThirdBehavior ]); } // implement corresponding setter ... set behaviors(val) { this._behaviors = val; } } |
And that’s basically all there is to it. Hopefully this article helped outline how Polymer Behaviors can easily be leveraged when implementing elements as ES6 classes. Enjoy.
amd, behaviors, es6, html imports, html5, javascript, polymer, shadow dom, wct, web, web components
It there a way to add a behavior dynamically in a component or in a behavior? Meaning, adding a behavior after a component/behavior already loaded