Thursday, June 18, 2015

Data Binding vs. Event Handling

Refactoring some of my projects from Polymer 0.5 (or earlier) to Polymer 1.0 I found myself using data binding and computed properties for situations where I previously had event handlers doing the "hard work". Since I think this is a rather nice and clean pattern  I thought I'd give some examples for this.

Let's take a look at a simple sample of a login. Using the google-signin element you could wait for the google-signin-success event to trigger and then retrieve/display information about the authenticated user and toggle the UI accordingly. Of course then you also have to handle the reverse case if a user signs out by listening for the google-signed-out event.

But the google-signin element also offers an is-authorized attribute / isAuthorized property that you can bind to and observe. Toggling the UI based on this property is as simple as adding hidden$="[[!isAuthorized]]" and hidden$="[[isAuthorized]]" to elements you want to show/hide. No extra JS necessary for this, as opposed to before where you had to set isAuthorized in the event handlers.
To retrieve user information once authorization has been granted you could add an observer to isAuthorized, but I think the much nicer solution is to make user a computed property that depends on isAuthorized. Whenever the value of isAuthorized changes this will re-evaluate the function and set the user property accordingly.

Let's take this sample a bit further. In many cases you will have to retrieve some more information from your server or elsewhere about the authenticated user. So you would need to trigger some request once the user is signed in and handle the response once it is available. In this sample I'm using my discovery-api-elements to fetch information about the user from Google+, but you can do something similar using iron-ajax or any other data-fetching element.

Instead of triggering the request manually, what you can do is binding the auto property (at least for discovery-api-elements or iron-ajax) to the isAuthorized property. Once isAuthorized and with it auto becomes true the request will be triggered automatically and you just have to handle the response.

But this won't remove the data in case the user signs out. To achieve this we make the data that is displayed (activities) a computed property that depends on both the response from the data-fetching element and the isAuthorized property.

Here's what happens now, when a user signs in:
  1. google-signin sets isAuthorized to true.
  2. This sets the auto property on the data element which triggers the request.
  3. Once the request completes plus-activities-list sets the response property accordingly.
  4. This change triggers recomputing activities with the _parseActivities function.
  5. Once there are items in the activities array, they will be displayed by the dom-repeat.
When the user signs out again:
  1. google-signin sets isAuthorized to false.
  2. This triggers recomputing activities which will be set to an empty list.
All of this without having to explicitly care about any event handlers, and provided another data- or sign-in-element offers similar properties you can bind to, you can simply replace those elements.