Show-flick - The Application

Being a fan and an adopter of AngularJS myself, I was very excited when Google released Polymer. It is not that I favor an alternative to AngularJS; it is rather that I praised the efforts for a library that focus on components. I celebrated through the introduction of Polymer - when encountering that this library also have mustache binding {{}}. Incorrectly, this induce me to think that Polymer could be a flexible transition from AngularJS.

I was fast attracted by the ability to import components through a single line. No need to inject JavaScript files based on components, no need on adjusting code to make room for the new code; if the component works then it works! This was to me an exciting idea. More exciting was for me to discover that there is a community on the road of web component already on their way.

I embarked in a path of creating an application with Polymer in an attempt to dig deep into the Polymer intrinsics. Needless to say that Polymer and AngularJS are very different in nature. This post is a description of the key important features I encounter with Polymer.

The application I created with Polymer is an application that enable a TV shows listing, display and view of various show TV titles. I named this application show-flicks in reference to similar tile display applications in the industry. In this application along with Polymer I utilized the Material Design.

Material Design

It has not been too long since Google Introduced Material Design. A new design principle which promise to be agnostic to all devices. The material principle lies in the utilization of an environment with 3D space. In a 3D space, objects have x, y and z dimensions. The key distinction here is that in the past design principles did not pivot in the utilization of the z-axis. The z-axis under this theorem is perpendicularly aligned to the plane of the display, with the positive z-axis extending toward the viewer.

The goal of material design as conveyed by Google is to create a visual language that synthesis classic principles of good design with the innovation and possibility of technology and science.

 

keynote_animation_material_design

 

Web Components

This a phenomena that have yet been occurring for some time. JQuery provided us a way to compartmentalize units of codes and functionality. However, dependencies and symmetry between libraries prevented us to fully compartmentalize. In the AngularJS realm we have module development. In addition Angular enable us directives, this enable us to bring functionalities into HTML tags to life.

Polymer and Components

The documentation on Polymer is comprehensive. The goal of this section is not to eco the same degree of documentation that is available. The goal is to aid in providing insight into the nature of this library, or even help a new adopter of this library.

The code below preview the anatomy of a polymer component.

   1: <link rel="import" href="../paper-button/paper-button.html">
   2:  
   3: <polymer-element name="my-element">
   4:  
   5:   <template>
   6:     <style>
   7:     .....
   8:     </style>
   9:     <core-card id="core_card" layout vertical>
  10:       <paper-button label="Paper Button" id="paper_button"></paper-button>
  11:     </core-card>
  12:   </template>
  13:  
  14:   <script>
   1:  
   2:     Polymer({
   3:       created: function(){},
   4:       ready: function(){},
   5:       attached: function(){},
   6:       domReady: function(){},
   7:       detached: function(){},
   8:  
   9:     }); 
</script>
  15: </polymer-element>
  16:  
  17: <!--Below is to Render the Element on the Page -->
  18: <my-element>
  19: </my-element>

In addition to the above lifecycle callbacks Polymer variables and events could be created contextually. If created within the Polymer context this variable or events could be accessible through the polymer objects. Polymer objects could be selected through their id by utilizing the this.$ notation.

   1: <script>
   1:  
   2:  
   3:     Polymer({
   4:       created: function (){},
   5:       ready: function (){
   6:           // variable created in my-element context
   7:             this.Message = "Hello World";
   8:       },
   9:       attached: function (){},
  10:       domReady: function (){
  11:           this.$.paper_button.label = "Click Me!";
  12:       },
  13:       detached: function (){}
  14:     });
  15:  
  16:   
</script>

clickme

Also importantly the blow describes how Polymer handles binding and event triggering.

   1: <link rel="import" href="../paper-button/paper-button.html">
   2: <link rel="import" href="../paper-input/paper-input.html">
   3:  
   4: <polymer-element name="my-element">
   5:  
   6:   <template>
   7:     <style>
   8:      ...    
   9:     </style>
  10:     <core-card id="core_card" layout vertical>
  11:       <paper-button label="Paper Button" id="paper_button" on-tap="{{ clicked }}"></paper-button>
  12:       <paper-input label="Type something..." willvalidate value="{{ Message }}" id="paper_input" layout vertical></paper-input>
  13:     </core-card>
  14:   </template>
  15:  
  16:   <script>
   1:  
   2:  
   3:     Polymer({
   4:       created: function (){},
   5:       ready: function (){
   6:           // variable created in my-element context
   7:             this.Message = "Hello World";
   8:       },
   9:       attached: function (){},
  10:       domReady: function (){
  11:           this.$.paper_button.label = "Click Me!";
  12:       },
  13:       detached: function (){},
  14:       Message: '',
  15:       clicked: function(){
  16:         this.Message = "Hello Again!";
  17:         }
  18:     });
  19:  
  20:   
</script>
  17:  
  18: </polymer-element>

PolymerRebind

Binding and Event Handlers on Repeats - The Polymer Way

A common AngularJS pattern I use consistently is the ng-click=”Myfunction(object)” I believed this pattern is a great helper on ng-repeat or even nested ng-repeat’s. I was astonish to realize that this pattern is not transmutable to Polymer events.

My first to go solution was to build a custom filter that will translate the full objects into JSON string this could simple be accomplish by using custom or global filters through Polymer. It was not until further search that I found out almost hidden in the api, that I could simply access bound models through the third parameter in the call back.

   1: <polymer-element name="x-foo">
   2:   <template>
   3:     <template repeat="{{user in users}}">
   4:       <div on-click="{{clickHandler}}">{{user.name}}</div>
   5:     </template>
   6:   </template>
   7:   <script>
   1:  
   2:     Polymer('x-foo', {
   3:       clickHandler: function(e, detail, sender) {
   4:         console.log(sender.templateInstance.model.user.name);
   5:       }
   6:     });
   7:   
</script>
   8: </polymer-element>

The Shadow-Dom Paradox

The era of web component brought a new creature to reality. This creature is the Shadow Dom. Web Components live in nested environments. Web components could not access elements inside other web components and manipulate them at will. This development framework require for the developer to be web component conscious and to understand scope.

Moreover, a dynamic application consist of many elements created at runtime yet not selectable. How can we observe when those elements are ready to further manipulate them at will? This is where the mutation observer came to the rescue.

In the below example I have a tile container – which is the container for all my tiles that would be generated at run time, when my tiles are ready I will store them in an array for their utilization at a later time.
   1: Polymer('tag-name', {
   2:   created: function() { ... },
   3:   ready: function() { 
   4:     // where tiles_container contains tiles generated at run time
   5:      this.onMutation(this.$.tiles_container, this.cardAdded);
   6:   },
   7:   tiles: [],
   8:   cardAdded: function (observer, mutations) {
   9:               console.log("mutation happen");
  10:               var that = this;
  11:               mutations.forEach(function (record) {
  12:                   record.addedNodes[1].visible = true;
  13:                   record.addedNodes[3].templateInstance.model.show.visibility = true;
  14:                   // Select the node of you interest
  15:                   that.tiles.push(record.addedNodes[3]);
  16:               }.bind(this));
  17:           }
  18:  
  19:   
  20: });

Responsiveness

I am not a design gentle by trait. As a result the more abstracted the themes and the styles for me, the more reason for celebration. Thankfully, Polymer has abstracted, similar to Bootstrap, many of the configuration that enables for an awesome look and feel. It is important to state that you could apply CSS if so you wish. My humble recommendation, however, is to work with the abstracted layer first, as these ones are the one fully tested on device rendering.

And thus by following this principle Show-flick standed as a responsive application IphoneTitleView IphoneFilter IphoneDetailView LandscapeView

Do Not Code Just Yet

As I stated before, Web Components have a thriving community of developers writing components. Do not write code just yet; check out all kinds of web components by visiting WebComponents.org and observe if there is a functionality you would likely be using in your next app.

The below view is a preview to a functionality created by utilizing the login-box which could be preview and found at the component.kitchen site. I customized the below web component for Gravatar Support.

LoginGravatar
Show-flicks is Not a Real Application This application was not develop with the intent to commercialize or be a real application of use. The development of this application was strictly a business case to discuss Polymer as an application development solution