Over a million developers have joined DZone.

Polymer: To Bind or Not to Bind

As one of the lucky guys who first got a chance to "play" with Polymer at Nuxeo, I normally get a lot of questions from people new to the framework. So, I thought it would be a good idea to start writing about some of the underlying concepts to help people understand the "Polymer way".

· Database Zone

Learn NoSQL for free with hands-on sample code, example queries, tutorials, and more.  Brought to you in partnership with Couchbase.

polymer-logoIf you’ve been following our blogs you know that we’ve been using Polymer to build a lot of cool stuff. In fact, we are using Polymer and Web Components more and more every day to build applications and I’m not just talking about our core development team, our solution architects are also having a great time building awesome proof of concepts... which I’d love to show and tell you all about, but then I’d have to kill you.

As one of the lucky guys who first got a chance to "play" with Polymer at Nuxeo, I normally get a lot of questions from people new to the framework. So, I thought it would be a good idea to start writing about some of the underlying concepts to help people understand the "Polymer way"–and of course, save me some time in the future .

Data Binding

One of the concepts I see people struggling with the most is data binding. This is one of those concepts we take for granted as it’s something we’ve come to expect from any modern framework. I’ve been a big fan ever since I started building Flash based RIAs (Rich Internet Applications) with Laszlo and Flex, more than 10 years ago, especially since both of them had nice declarative syntaxes for data binding. So, it has become a part of my toolbox.

Polymer has built-in support for data binding. Although in the early Polymer versions (pre 1.0) more complex expressions were supported, it did feel a bit too "magical" and its expressiveness came at a huge cost in terms of performance. So with Polymer 1.0, the team introduced a very simple and clever implementation built around the Mediator pattern.

It’s so simple that whenever I see someone struggling with it I really enjoy explaining the underlying concepts and implementation and don’t let them get away until they understand it fully (sorry guys!).

Starting at the very beginning, the whole idea with data binding is to be able to "bind" an element’s property to another property or attribute of another element. In Polymer, this means we are binding/mapping/connecting/synchronizing a property from our custom element, the host, to a property or attribute of one of its child elements. What’s important to take from here is that the property always "exists" in our custom element. This means that even if you’re thinking Hey, I’m just binding this property from this child element to this other property in this other child element the fact is that it always goes through a local property in your custom element, even if you don’t explicitly declare it. That’s why this is the Mediator pattern–our custom element is mediating these bindings.

The best way to really understand what’s going on is to take a peek under the hood. So, let’s take an example—based on the awesome “Thinking in Polymer” talk by Kevin Schaff during last year’s Polymer Summit–and remove the "sugar" that Polymer adds, layer by layer.

Let’s say we’re building a "polite-element":

<dom-module id="polite-element">
  <template>
    <p>What should I call you?</p>
    <input value="{{name::input}}">
    <p>Welcome <span>[[name]]</span>!</p>
  </template>

  <script>
    Polymer({
      is: 'polite-element',
      properties: {
        name: {
          type: String
        }
      }
    });
  </script>
</dom-module>

Our custom element has an <input> whose value is bound to a "name" property. Since our element is very polite, whenever this name changes, we say welcome to the person.

Let’s focus for now on the first data binding expression:

<input value="{{name::input}}">

Here we are using a two-way binding, which you can tell by the use of curly brackets {{name}}. This means that whenever "value" changes, our "name" property will be updated accordingly.

The "::input" suffix specifies which event should trigger the binding, so we’re just listening for an "input" event and updating our "name" property to <input> value. Let’s try replacing this binding with our own version of it to see if it’s that simple:

Note: You normally just need to explicitly add this suffix when using a two-way binding to native elements or to non-Polymer elements.

<dom-module id="polite-element">
  <template>
    <p>What should I call you?</p>
    <input id="input" on-input="_inputChanged">
    <p>Welcome <span>[[name]]</span>!</p>
  </template>

  <script>
    Polymer({
      is: 'polite-element’',
      properties: {
        name: {
          type: String
        }
      },
      _inputChanged: function(e) {
        this.name = e.target.value;
      },
    });
  </script>
</dom-module>

And, that easily, our first data binding expression is now gone!

Now, let’s focus on the next one:

<span>[[name]]</span>

In this case, we’re using one-way binding since our <span> won’t make changes to the "name" property. The idea here is to update our <span>'s text content with the value of our "name" property whenever it changes, so let’s try adding an observer to listen for these changes and handle the text content update ourselves:

<dom-module id="polite-element">
  <template>
    <p>What should I call you?</p>
    <input id="input" on-input="_inputChanged">
    <p>Welcome <span id="name"></span>!</p>
  </template>

  <script>
    Polymer({
      is: 'polite-element',
      properties: {
        name: {
          type: String,
          observer: '_nameChanged'
        }
      },
      _inputChanged: function(e) {
        this.name = e.target.value;
      },
      _nameChanged: function() {
        this.$.name.textContent = this.name;
      }
    });
  </script>
</dom-module>

Note: the "this.$.name" is accessing the <span id=”name”> element.  Any element with an id is automatically stored on a this.$ map for convenience.

Not that hard, right? But some of you may say I’m kind of cheating here since I’m still relying on a property and an observer... that’s why Polymer is still working its "magic". So, let’s get it down to a bare minimum and remove the property and observer altogether, replacing these with a simple getter and setter:

<dom-module id="polite-element">
  <template>
    <p>What should I call you?</p>
    <input id="input" on-input="_inputChanged">
    <p>Welcome <span id="name"></span>!</p>
  </template>

  <script>
    Polymer({
      is: 'polite-element',
      _inputChanged: function(e) {
        this.name = e.target.value;
      },
      get name() {
        return this._name;
      }, 
      set name(v) {
        this._name = v;
        this.nameChanged();
      },
      nameChanged: function() {
        this.$.name.textContent = this.name;
      }
    });
  </script>
</dom-module>

That’s it! As you can see there’s really no magic, Polymer just adds some "sugar" and makes your custom elements more declarative and easier to understand!

This is a very simple example but I hope it made it clear how much complexity is removed if you start thinking in Polymer and start leveraging data binding, observers, expressions, and computed properties to bring your custom elements to a whole new level.

Finally, here are some quick closing remarks: as pretty much anything else there are pros and cons to data binding and it does tend to have a bad reputation, especially two-way data binding since it can become a nightmare to debug and to understand the data flow when used extensively in bigger applications. That’s one of the reasons why new patterns like Flux are gaining popularity but as we all know there’s no silver bullet, and as long as people are aware of its pros and cons, I think it’s a solid choice that should be part of your toolbox when building your applications.

Have fun!

The Getting Started with NoSQL Guide will get you hands-on with NoSQL in minutes with no coding needed. Brought to you in partnership with Couchbase.

Topics:
polymer ,binding

Published at DZone with permission of Nelson Silva. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}