now-playlist

From Angular ES5 Directive To Angular ES2015 Component (ES6)

Recently, I started refactoring Echoes Player, my open source project, from angular ES5 to angular 1 with ES2015 (former ES6). I’m following several concepts and i’de like to share the process of converting an angular 1 directive  written with es5 to an angular 1 component using ES2015.

Why Using ES2015 With Angular 1

I think that one of the most important reasons to start using ES2015 with angular 1 is in preparing current angular 1 code to migration, when the time comes, to angular 2 code.

I’ve written before about 5 steps to prepare your angular 1 code to angular 2, and 3 more steps to follow as well.

ES2015 is the new and current standard for writing javascript. It has taken a very long time to close the spec, however, now that the spec is closed, more and more libraries, frameworks, blog posts and tutorials are using it.

ES2015 features a very nice collection of new syntax and new methods for achieving several operations in less code (sometimes), more readable code and new types for handling collections (like Map and Set).

Moreover, Angular 2 is written with ES2015 and Typescript. This will assist in code migration to angular 2.

Lets Start!

1. Angular 1 With ES5

I’ll use one of the modules i’ve written in Echoes Player with ES2015, and will convert it to a directive/component with ES2015.

Echoes Player is a media player that is based on youtube api (it’s open source as well). In its layout, it consists a sidebar, a top search bar and a content area. The sidebar include the “now playing” playlist that lists the tracks that currently queued to play.

Since I added this feature fast, I didn’t create a module for it – I used angular’s directives (ng-repeat) and added few more properties to the controller of this scope.

“Now Playlist” Html Template

taken from the index.html file:

Aside from using angular’s built-in directives, this tracks in this playlist are draggable (i’m using the angular-sortable-view module). The tracks can be removed from this list as well.

“Now Playlist” Controller

The controller for this template is defined above the “ul” element. This is the “UserPlaylistsCtrl” that can be found in the user-playlists.ctrl.js:

This controller serves other purposes beside the now playlist feature. The relevant properties and functions that the now playlist uses, are marked with a comment above it.

2. Decisions Taken Before Converting ES5 to Es2015

The inspiration for refactoring the code comes from angular-class boilerplate of using angular with es2015. In the process of refactoring this code and converting it to ES2015, I had to decide how to isolate the several features in this area. Creating the “Now Playlist” component is one of these decisions.

Defining A New Component For “Now Playlist”

First, I wanted to redefine the html template to be used as a web-component (or rather an html tag). After much thought, I came up with this component:

I decided to expose the relevant attributes in order to keep the logics in one “smart” component (the “now-playing” component) and keeping this component as stateless as possible.

Creating Files For “Now Playlist” Component

The next step was to generate the appropriate boilerplate of files for this component. For generating these files, I used “gulp-dogen” – an npm module I wrote for this repetitive task of generating directories and files for a certain purpose.

“gulp-dogen” takes the name of the component from a cli command, then it adds this name in all of the files where you specify it, and created a new directory with the new files in it.

Finally, I came up with these files:

I’m using the “index.js” notation, similar to node.js require syntax, so I can simply import the now-playlist component as such:

index.js – Module & Directive Defintion

This file defines the angular module and its accompanied services and directives. This is also the place for importing any dependant modules – like the angular-sortable-view module. Finally, It exports the now-playlist module, so it can be consumed by other modules.

now-playlist.component.js – The Directive Definition

This file includes the directive/component definition for this module. Currently, I’m using angular v.1.4.8, where the new “component” syntax for creating an element directive isn’t included.

This file imports the controller and template of this directive from an external file. I defined this directive with all of the properties that will be included within the “component” syntax –

  • bindToController: true – binds external attributes to “this” context in the controller
  • restrict: ‘E’ – since it’s a “component” – it’s an element tag
  • replace: true – since there is no support for real web components yet
  • controllerAs: ‘nowPlaylist’ – this follows angular 2 convention as well – exposing this as the camel-case version of this element tag.

There will be less code in this file once the new “component” function is available. Also, it will need to export an object (json) rather than a function.

now-playlist.ctrl.js – The Component’s Controller

This file includes the logics and view model for this component’s view. I used ES2015 “class” defintion, since controllers in angular 1 are created with the “new” keyword. Notice that “this” context, is overloaded with more properties that are defined as part of the scope. Apart from the “constructor” function, I created

now-playlist.tpl.html – The Component’s html

This file contains the html template that was in the index.html. Few things have changed:

  • The code now references to the ‘controllerAs’ alias “nowPlaylist”
  • The “ul” is wrapped with a “section” element
  • The “css” classes now reflects the correct meaning – “now-playlist”, “now-playlist-track”

Eventually, I also moved the relevant css/less rules to the “now-playlist.less” file.

Usage of “Now Playlist” In A Broader Context

Finally, the area that contains the now-playlist and 2 other components, has been also refactored in the same way-

  • a small toolbar for filtering the playlist, clearing the tracks and save the playlist
  • a form component for typing a name to save the playlist to the current signed-in youtube’s user

This is the smart component “now-playing” html template code (I still have work to do – this ng-if expression should be changed):

Final Thoughts

The process of converting the code gave me the opportunity to restructure the app, rethink in a component base architecture and eliminate some of the code. Now, the code is more modularised, organised with components, defined with ES2015 and is ready for angular 2 – with some minimal changes I believe.

Moreover, this process should be taken step by step. It can be an iterative process and be applied to each component – one at a time.

The source code for Echoes Player with ES2015 is still a work in progress. The commits are documented in #84 as well.

However, this is not all. I plan on writing more articles on this process – as it contains much more preparation and adjustments.

I started gathering these concepts in an “Angular ES2015 Style Guide” – You are welcome to collaborate on this style-guide – suggest and add your thoughts.