Front-End Insights

Polymer explained: data binding

PolymerProgramming

Ok, so after the introduction to Polymer it’s time to learn something more. Today we will dig into the subject of data binding, cause it’s one of the most important things in every framework/library.

Types of data binding in Polymer

We have two types of data binding in Polymer: one-way data binding where the data flow is downward and two-way data binding.

To define the binding you have to use suitable annotation. For example:

<custom-element data="[[name]]"></custom-element>

In the example above we bind the ‘name’ property of the host to the data property of the custom-element (child) component.

We have two types of binding annotation:

  • [[]] defines one-way data binding only – the data can be changed only on the host side and affects the child
  • {{}} defines automatic data binding which can be one-way as well as two-way (if the target property of the child component is declared as two-way)

One-way data binding

Let’s take a look at an example of this type of data binding.

<dom-module id="child-component">
  <template>
    Hello {{who}}
  </template>
  
  <script>
    Polymer({
      is: 'child-component',
      properties: {
        who: {
          type: String
        }
      }
    });
  </script>
</dom-module>

<child-component who="[[name]]"></child-component>

First of all, please look at the last line of the example. This is how we use one-way data binding to pass the name property of the parent component (assuming we use the child-component inside another component). In this case, the data written in the name property can be changed only in the parent component. During the binding process the value is written in the who property of the child. Even if you change the value of the who property, this change is ignored by the parent and is not reflected on the name property.

One more (interesting) thing here… We also used data binding to link the template of the child-component with its property (who). As you can see, here I used automatic binding – actually it doesn’t matter and you can use the one-way binding here ([[]]) as well. Bindings between a template and properties of the component are always one-way!

Automatic binding

The second type of binding in Polymer is automatic binding. This type of binding is fully configurable so, thanks to this, you can achieve two-way data binding, as well as, for example, one-way binding with the flow direction upside-down.

Firstly, please see below an example of the two-way data binding:

<dom-module id="child-component">
  <template>
    Hello {{who}}
  </template>
  
  <script>
    Polymer({
      is: 'child-component',
      properties: {
        who: {
          type: String,
          notify: true
        }
      }
    });
  </script>
</dom-module>

<child-component who="{{name}}"></child-component>

This time (please take a look at the last line) we use a different annotation ({{}}). The second difference is in the properties declaration. If we want to achieve classic two-way data binding we have to add and set the notify property to true. By doing so, we tell Polymer that we want to notify the parent about every change of this child property.

The second example shows how to achieve the upside-down direction of the flow (when every change of the child’s property is visible in the parent component but changes in the parent property is ignored by the child component):

<dom-module id="child-component">
  <template>
    Hello {{who}}
  </template>
  
  <script>
    Polymer({
      is: 'child-component',
      properties: {
        who: {
          type: String,
          notify: true,
          readOnly: true
        }
      }
    });
  </script>
</dom-module>

<child-component who="{{name}}"></child-component>

As you probably noticed, we added an additional property to the object which sets up the who property. By doing this, we actually have a classic two-way data binding but with a blocked ability to change the child.

The next example shows that we can use automatic binding to set up a classic one-way data binding:

<dom-module id="child-component">
  <template>
    Hello {{who}}
  </template>
  
  <script>
    Polymer({
      is: 'child-component',
      properties: {
        who: {
          type: String
        }
      }
    });
  </script>
</dom-module>

<child-component who="{{name}}"></child-component>

As you can see, when we omit the notify property when setting up the who prop, we actually get the same effect as if we were using the [[]] annotation.

The last example won’t work at all:

<dom-module id="child-component">
  <template>
    Hello {{who}}
  </template>
  
  <script>
    Polymer({
      is: 'child-component',
      properties: {
        who: {
          type: String,
          notify: true,
          readOnly: true
        }
      }
    });
  </script>
</dom-module>

<child-component who="[[name]]"></child-component>

When we use the [[]] annotation together with the notify and readOnly properties set to true, we have a situation where changes in both directions are ignored.

Binding different types of data

In this paragraph I will focus on binding properties into templates. The simplest case is to bind the text (actually you may have noticed it already in the previous examples):

<template>
  Hello {{who}}
</template>

As you can see, to bind a property to the template, just use the annotation with the name of the property inside.

You can also bind it to the attributes:

<template>
  <img src$="https://www.example.com/profiles/{{userId}}.jpg">
</template>

Please note the src$ attribute (actually it’s $= instead of =) – it’s a special attribute binding provided by Polymer.

Computed bindings are also very helpful in everyday development:

<dom-module id="custom-component">
  <template>
    Hello <span>{{computeFullName(first, last)}}</span>
  </template>

  <script>
    Polymer({
      is: 'custom-component',
      properties: {
        first: String,
        last: String
      },
      computeFullName: function(first, last) {
        return first + ' ' + last;
      }
    });
  </script>
</dom-module>

In the last example are arrays which are a special case… Polymer doesn’t support binding to array items by the index. You can only bind to the specific properties of the array item (if it’s an object). So, the below code is disallowed:

<span>{{array[0]}}</span>

Only below code is allowed:

<span>{{array[0].name}}</span>

The other way is to create a computed binding but this is a story for a whole other blog post.

Summary

Data binding in Polymer is not very different from other front-end frameworks and libraries. This subject is important to get familiar with before you start development in this environment but, as you can see, it’s nothing special and you will learn it quickly.

Related Post

I recommend Nozbe

Simply Get Everything Done

Get your tasks and projects done thanks to Nozbe system and apps for the Mac, Windows, Linux, Android, iPad and iPhone.

If you want to know more about Nozbe and its capabilities, please take a look at my article about this great application.