Friday, November 25, 2016

Using Polymer Material Design components with Angular 2

In 2014 Google released a standard design language called Material Design.  It's an impressively detailed specification, with guidelines for pretty much every aspect of modern UI design, down to and including controls.  Depending on the JavaScript framework you're working with, there are different ways to implement Material Design in your application.

In Aurelia, there's a very well developed solution from the angular-ui-toolkits group, the aurelia-materialize-bridge.   I definitely recommend if you're working with Aurelia to check out this library. Most of the Material Design functionality is available and implemented, along with robust styling support. 

If your project is using Angular 2, then the official home for Material Design is at the angular/material2 repo on GitHub.  While there are a number of good building blocks either out there, or in progress, there's also quite a bit missing.  It's currently in alpha, and there's still a lot of work to do.   But if you're wanting to have something more mature, there's an interesting solution using another Google library.

Google Polymer, a Web Component based UI design language, is home to an extensive array of controls in the Material Design format.  The functionality provided by these components is currently significantly more robust than the Angular2 versions.  While these do not natively integrate with Angular2, the folks at Vaadin have implemented a way to get around that.  This is functionality that they're released as an npm package - angular2-polymer.   Rather than me try to explain it myself, I'll use their own words:

The angular2-polymer is a directive factory that aims at bridging the gaps between using Polymer based Web Components in Angular 2 applications.
It scrapes the Polymer element API in order to define Angular 2 outputs and inputs, to apply the ngControl and the ngForm directives, and to observe DOM changes updating the element’s DOM tree appropriately.
 
So I went about following the instructions for integrating Polymer into an Angular2 application.  I have to admit I was soon disappointed with a couple things:
 
  1. Polymer is still using bower for distribution.  There's no npm versions of the polymer controls, and for someone working in Angular2, which has left bower behind, it's feels wrong to go back to having dependencies in bower.
  2. There is no CDN support for Polymer.  I was able to find some "non production ready" CDN's based on the GitHub CDN, and also some old versions of Polymer, but nothing current or official.
But my urge to try the controls was greater than the urge to avoid bower, so I installed it globally, added a bower.json to my project, and proceeded to bring in the various input controls I needed.  At the end, the dependencies in bower looked like this: 


Next, I added a copy step to Webpack to pull in the files to the dist location, and added references to the dist location files to the  index.html.  

The last setup in configuration was to follow the suggestion of a custom "on ready" script checking for web components before loading the angular 2 application:

I then pulled in all the components into a module in Angular2, which is imported into the module housing the Angular 2 components you want to add polymer to:

Finally, I added the polymer controls to my component template, fired up the app, and...it worked.  I had polymer Material Design inputs in my web forms.
 
I was able to hook them up to the model, and get databinding to work without a problem.  For anyone interested in trying out Material Design for Angular2, I definitely recommend you check out the Vaadin angular2-polymer package.  Until all the elements are fully available as native Angular2 components, this is a decent way to get started with Material Design with Angular 2.