The last time Hackerfall tried to access this page, it returned a not found error. A cached version of the page is below, or click here to continue anyway

Declarative web applications with Polymers two-way data-binding Futurice

Lately Ive been having a lot of fun with Googles Polymer, trying out different patterns of creating web apps with it. Polymer is a future-oriented frontend library based on Web Components standards. I have a strong feeling Web Components will fundamentally change the way we build the web.Polymer is justone of the libraries that try and make using them as easy as possible.

Polymer authors are quite big on declarative. They argue HTML used to be entirely declarative in the days of yore, but has failed to keep up with the times. Custom Elementsare the solution to this discrepancy: just like a <select> element magically transforms into the dropdown we all know, we can now define our own Custom Elements, that can have functionality of their own.

In order to try out thedeclarative pattern,I set out to create a currency converter with as little JavaScript as possible, trying to leave all the heavy lifting todata-bindings alone.

This is what well end up with, so hold on to your hat and enjoy the ride!

Step 1. Must-have pieces of UI: the template

Polymer uses the familiar AngularJS handlebars expression syntax for the data-binding:

{{ value | filter }}

Using this syntax, we can do something like the following to arrive at an almost-working solution.

<input value="{{ amount }}">
<input value="{{ fromCurrencyRelativeValue }}">
<input value="{{ toCurrencyRelativeValue }}">
<div class="result">
    {{ (amount * (fromCurrencyRelativeValue / toCurrencyRelativeValue)) }}"
</div>

In essence, in the result div we have a simple calculation expression: the amount entered multiplied with the fraction of the relative values.

However, there are no restrictions on what the `fromCurrencyRelativeValue` and `toCurrencyRelativeValue` can be, which would definitely be a problem.

Step 2. Make it work

There is a small amount of Polymer boilerplate that we need to get over with to make the element do its thing. It looks a little something like this:

<polymer-element name="currency-converter" attributes="amount fromCurrency toCurrency">
  <template>
    <!-- The above stuff here. -->
  </template>
  <script>
    Polymer({
      // New stuff here?
    });
  </script>
</polymer-element>

See how I added the variables as the elements attributes? This allows us to use the element like so:

<currency-converter
  amount=100
  fromCurrency=0
  toCurrency=1>
</currency-converter>

But back to the topic. The JS part in the boilerplate above is for defining the Custom Elements prototype. We could of course define the currencies elsewhere (as an attribute or even using an external JSON resource), but for this demo, lets go ahead and add the data straight to the converters prototype.

Polymer({
  /**
   * The data model holds currencies' names and relative values.
   */
  currencies: [
    {
      name: "EUR",
      relativeValue: 1.13085
    }, {
      name: "SEK",
      relativeValue: 0.1189895
    }, {
      name: "USD",
      relativeValue: 1.0
    }, {
      name: "NOK",
      relativeValue: 0.1311897
    }, {
      name: "JPY",
      relativeValue: 0.00836764
    }
  ]
});

Okay, now we have the HTML template from Step 1, the necessary boilerplate, and the data model. Its all good! But lets not stop while were having fun!

Step 3. Usability and swag

The text input for selecting a currency index is obviously a poor decision, but while were at it, why not decorate all of the stuff with some Material Designgoodness?

<paper-input-decorator floatingLabel label="Amount">
  <input is="core-input" type="number" value="{{ amount }}">
</paper-input-decorator>
<!--  -->
<paper-dropdown-menu label="From" flex>
  <paper-dropdown class="dropdown">
    <core-menu class="menu" selected="{{ fromCurrency }}">
      <template repeat="{{ c in currencies }}">
        <paper-item>{{ c.name }}</paper-item>
      </template>
    </core-menu>
  </paper-dropdown>
</paper-dropdown-menu>

Also, lets add a swap button for quick to-fro:

<div class="swap" on-tap="{{ swap }}">
  <core-icon icon="swap-horiz"></core-icon>
</div>

Finally, show the result witha label above it:

<section class="result">
  <p class="description">
    {{ amount + ' ' + currencies[fromCurrency].name + ' in ' + currencies[toCurrency].name }}:
  </p>
  <p class="result-number">
    {{ (amount * (currencies[fromCurrency].relativeValue / currencies[toCurrency].relativeValue)) | toFixed(2) }}
  </p>
</section>

Phew, thats it! All we need to do now is define the two functions we are now referencing: the `swap` method and the `toFixed` filter. They are very simple.

/**
 * Filter for bringing numbers to a defined precision.
 */
toFixed: function(value, precision) {
  return Number(value).toFixed(precision);
},
/**
 * Method that swaps the two selected currencies with each other.
 */
swap: function () {
  var temp = this.fromCurrency;
  this.fromCurrency = this.toCurrency;
  this.toCurrency = temp;
}

Step 4. Admire our accomplishments

The demo page over on GitHub hosts 3 separate `<currency-converter>` elements. Their invocations are described below each element like so:

All of the code is available too, the gist of it being the Custom Element file weve been going through here.

Demo: http://ohanhi.github.io/declarative-polymer/ Code: https://github.com/ohanhi/declarative-polymer/

Happy hacking!

Continue reading on futurice.com