As you might have noticed, we at Vaadin have been experimenting with bringing our Grid and Charts components to a new audience by wrapping them into Polymer elements. Polymer is Google’s project to bring Web Components into developers’ hands and into production.
I wanted to give the new elements a try in a mobile-first fashion, and with the help of our designer Tuomas Nironen, we came up with a design for a fitness tracker application. I could have gone with the Polymer Starter Kit, but instead, I wanted to start fresh and learn all the bits and pieces the hard way.
The application consists of two screens – a summary view of the user’s weekly activities compared to their goals and a more detailed list view of all workouts during the selected week.
If you wish to follow along in code, just take a git clone of the project, open the folder in your favorite code editor and run the application with the following command.
npm install && bower install && gulp
Or you can open up the live application from our demo server.
Transitioning between views
Especially on mobile, people have grown to expect smooth transitions between views and different states of the application. To implement transitions between the two views, I used the <neon-animated-pages> element from the Polymer Catalog. Both views were implemented as independent custom elements, which include the Polymer.NeonAnimatableBehavior to bring in support for entry and exit animations. The end result looks great without too much effort.
Another place for transition animations are the set summary rings displayed prominently on the summary view. While the user is navigating between different weeks, the progress towards weekly goals is animated to indicate the change of context. For this feature, I forked another element called <progress-bubble> which I had created earlier. With small tweaks to the animations and styling, it was pretty easy to achieve the result our designer had visioned.
Accessing the data
All workout data in this demo application is stored in static JSON files. However, these could easily be replaced with a Node/Express/Mongo-based backend or something similar. Access to this data is done inside a custom element called <fitness-tracker>, which acts as the parent for everything in the application.
This custom element uses the <iron-ajax> element to bring in the data from the server. While at first thought using a custom element for Ajax requests sounds a bit counterintuitive, I eventually grew to really like how it enables declarative Ajax requests without hardly any JavaScript code. After receiving the JSON responses, I used Polymer’s excellent data-binding features to trickle down the needed data to both views of the application.
Vaadin Grid and Charts
The workout listing view is all about <vaadin-grid>. The data provided by the parent element is used as the data source for the Grid. The most prominent feature utilized here are the row details. You can try this by selecting a row from the Grid. The select event is used to trigger the Grid to open row details for the selected row.
The detailed information uses the <google-map> element to display the workout route from a standard KML file. Below the map, there is also a visualization of speed vs. altitude using Vaadin Charts, which provides a nice way to declaratively configure the chart and also use Polymer data binding to bring in the values.
Bring it offline
One of the requirements for this demo application was to have it work even without a connection to the internet. For the purposes of this demo, I decided to go with the Application Cache. Instead of manually listing all the files in the manifest file, I configured a Gulp task for this job. As one might expect, there was an existing Gulp plugin for the task called gulp-appcache. For a more advanced offline treatment, I would suggest to take a closer look at the Polymer platinum elements.
Final touches
After being mostly done with the application, I wanted to optimize it for production. I already had a separate elements.html
for all HTML imports, so it was pretty easy to write a Gulp task to combine and minimize the imports to a single file using vulcanize and polyclean tools.
Even after running these tools, I noticed how the application was still displaying a blank screen for some seconds before everything was ready. Most likely the application has a lot of opportunities for optimization, but for now I decided to simply display a splash screen during loading. I used ideas from Eric Bidelman’s excellent Gist and managed to display the application icon in the center of the screen until everything was loaded.