Properties

Properties are used for data binding, which is an essential part of any modern web framework.

Let’s consider a component that demonstrates binding abilities of Polymer. It is an input where users can type something, and all they are typing is duplicated below by using property binding.

Guesser component

Source code

index.html
<html>
<head>
	<link rel="import" href="src/polymer-basic/properties/name-guesser.html">
	<script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
</head>
<body>
    <name-guesser placeholder="Your name goes here"></name-guesser>
</body>
</html>
src/polymer-basic/properties/name-guesser.html
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<!-- iron-input is a Polymer element from standard Polymer library. -->
<!-- It enhances standard HTML input by providing an ability of two-way binding. -->
<link rel="import" href="../../../bower_components/iron-input/iron-input.html">

<dom-module id="name-guesser">
  <template>

    <h4>
      Please enter your name:
    </h4>
    <!-- iron-input works as a wrapper for a simple HTML input -->
    <iron-input bind-value="{{name}}">
      <input placeholder="[[placeholder]]" />
    </iron-input>
    <br/>
    <br/>
    <div>
      Your name is: [[name]]
    </div>

  </template>

  <script>
    class NameGuesser extends Polymer.Element {
      static get is() {
        return 'name-guesser';
      }

      static get properties() {
        // Properties configuration object contains a map of properties.
        // Key is a name of a property, value is a configuration.
        return {
          name: String,
          placeholder: {
            type: String,
            value: 'Your name please'
          }
        }
      }
    }

    customElements.define(NameGuesser.is, NameGuesser);
  </script>
</dom-module>

There are two types of binding:

  • [[ ]] - one-way binding. An enclosed component listens to changes of a property and refreshes its state. In other words, the data flows downward - from the host component to children components.

    In our example, the placeholder property uses one-way binding: we just pass its value down to the input component.

  • {{ }} - two-way binding. An enclosed component not only listens to property changes but can also change the property value itself. That is the data can flow both ways - from host to children and back.

    In our example, the name property uses two-way binding to receive a value from the iron-input component and display it in div.

In this example, we could use two-way binding for all properties and the component would still work as expected. But it’s important to choose a correct binding, because it increases code readability and simplifies refactoring. Always prefer one-way bindings and use two-way bindings only when necessary.

A Polymer component can configure all its properties in an object returned by the properties getter. It can just specify a type of a property (String, Boolean, Number, Object, Array, Date) or provide a number of different parameters. One of these parameters is value which specifies a default value for the property.

In our example, the placeholder property has default value "Your name please". But it’s overwritten with "Your name goes here" passed from the host name-guesser element defined in index.html. We could also provide a name, e.g.

<name-guesser name="Charlie"></name-guesser>

That would cause the input to be filled on initialization:

Apart from value, a property can have a number of other attributes (observer, notify, etc.) that partially will be reviewed further.

Pay attention to the following important detail: properties are named in CamelCase in JavaScript but in kebab-case in HTML. For example, the bind-value property of the iron-input component is defined in the source code of the component as follows:

...
properties: {

  /**
   * Use this property instead of `value` for two-way data binding.
   */
  bindValue: {
    type: String
  },
  ...

Also, there are some native properties like class that do not support property binding. You should use attribute bindings instead to interact with such properties.

What we have learned so far
  • Use [[ ]] for one-way binding.

  • Use {{ }} for two-way binding.

  • Describe your properties in an object returned by the properties getter.

  • For each property you can define type, default value and a number of other parameters.

  • You can provide properties from outside of a Polymer component by using HTML attributes.

  • iron-input is a Polymer component that allows you to use two-way binding in input element.