Friday, 5 January, 2018 UTC


Summary

The custom elements specification allows for the use of properties and attributes in a custom element. Polymer makes it easier to use properties and adds to their capabilities giving you even more power đź’Ş when building components.
Declaring Properties
When we generate a Polymer element using the Polymer CLI we automatically get a property attached to our element.
static get properties() { return { gatorName: { type: String, value: 'Cayman' } }; } 
Properties are defined in a public getter method named properties. Each of these properties contains a set of key-value configurations.
In the example above, a property with a name of gatorName is defined.

Attributes property mapping in Polymer

If we have an attribute on the custom element that is named the same as a property, the value of that attribute will be set to the property value by Polymer.
<my-element gator-name="Crocodilian"></my-element> 
This will override the default value of gatorName with “Crocodalian”
Property Options
We have the type and value properties defined for the gatorName property. We can have a number of other options on these properties as well.
  • type The type will be used for transforming the data defined in an template attribute into a property value. The types supported out of the box are: String, Number, Boolean, Date, Array and Object. If needed, we can add support for other types.
  • value Default value for the property. Can be useful when we need a default behaviour.
  • reflectToAttribute Sometimes we need the property changed in the component to show in the element attribute. This can be especially useful for styling on condition. Setting this value to true will reflect the property on the element’s attribute.
  • readOnly As the name suggests, this prevents attribute values from mapping onto the property. We’ll have to use private setters to set the values
  • notify The Polymer properties are automatically data bound. By setting notify to true, we can get Polymer to fire events on property value changes.
  • computed Makes the property read-only virtual value that depends on other properties. We can define a method that takes multiple params as a string. For example, computed: 'getAge(dateOfBirth)' would run the getAge method with the dateOfBirth property’s value and return the output.
  • observer This is a string property that wil be evaluated as a function name to be executed on property change.
Using Properties
Once defined, we can use the properties in the component code or in the template itself.

Using properties in the component code

To use the property in the component code, we can simply refer them to using the this reference of the class.
printGatorName() { // this.gatorName refers to the current property value console.log(this.gatorName); } 

One-way property binding in the template

To use the values in the template, we can leverage the data binding support in Polymer.
We can use double square bracket notation for one-way data binding - [[value]]. This will allow properties to go from the component down to the template, but not the other way around.
<h2>Hello [[gatorName]]!</h2>
This would display the gatorName property’s value on the template.

Two-way property binding in the template

Polymer also allows for two-way data binding using the double curly braces notation - {{value}}.
As the name suggests, two-way data binding ensures that the template and component values are kept in sync.
<h2>Hello [[gatorName]]!</h2> <input value="{{gatorName::input}}"> 
In the above example, the value will be updated in both reference points when input changes. The default property value will display at the start, but when the user changes the value in the input, the value updates both in the input and the h2.
::input has to be used here since we are using a non-polymer input element.
Putting it All Together
With all the information we’ve learned so far, we can create a simple counter element similar to one created in the Stencil article.
<dom-module id="my-counter"> <template> <style> button, span { font-size: 3rem; font-family: monospace; padding: 0 .5rem; } button { background: pink; color: black; border: 0; border-radius: 6px; box-shadow: 0 0 5px rgba(173, 61, 85, .5); } button:active { background: #ad3d55; color: white; } </style> <div> <button type="button" increment on-click="handleIncrement">+</button> <span>[[value]]</span> <button type="button" decrement on-click="handleDecrement">-</button> </div> </template> <script> class MyCounter extends Polymer.Element { static get is() { return 'my-counter'; } static get properties() { return { value: { type: Number, value: 0, reflectToAttribute: true, }, increment: { type: Number, value: 1, }, min: { type: Number, value: 0, }, max: { type: Number, value: 1000, } }; } handleIncrement() { let incrementedValue = this.value + this.increment; this.value = this.isInRange(incrementedValue) ? incrementedValue : this.value; } handleDecrement() { let decrementedValue = this.value - this.increment; this.value = this.isInRange(decrementedValue) ? decrementedValue : this.value; } // checks if the value is within min max values isInRange(checkValue) { return checkValue >= this.min && checkValue <= this.max; } } window.customElements.define(MyCounter.is, MyCounter); </script> </dom-module> 
This code should be easy to follow. The only topic that we haven’t covered are the event handlers.
<button type="button" increment on-click="handleIncrement">+</button>
This is to call the handelIncrement method when the onClick event on the button is fired.
Conclusion
Polymer makes it trivial to define properties, makes it easier to set property values from attributes and also enables us to easily bind data.
When comparing to the Web Component implementation, Polymer makes it much easier to build fully functional Web Components.