Migrating A Component To Angular 2: From Angular 1.x & Es2015

Following Echoes Player article series about angular & ES2015, I decided to develop this project with angular2. I intend to write a series of articles about my experiments with angular2. In this post, i'm sharing first insights about starting with angular2 and converting the youtube-media component written with angular1 and ES2015 to angular2 and typescript.

Angular 2 environment setup

In order to start Echoes Player development with angular 2, I cloned AngularClass repository angular2 webpack starter boilerplate. The initial setup is pretty straight forward. I followed the quick start instructions and got a fully working environment that enables me to start playing with angular2.

Echoes Player is an open source media player for searching and playing videos from youtube (no ads).

Customising the angular2 starter

In Echoes Player angular1 ES2015 version, i'm using a slightly different directory structure (which I wrote about and present in the angualr1 ES2015 style guide).

In order to align with the first version of Echoes and ease the migration process, I added a new "core" directory, where I differentiate between core components and core services that the application will consume.

I also added a less loader to webpack-config in order to support loading less files. However, currently, the app loads the production style.css file of Echoes.

I also added a copy instruction to webpack-config to handle the fontAwesome fonts directory that i'm using to copy src/fonts into webpack dev server directory in development mode.

Converting YoutubeMedia Component

I created a new directory in "core/components/youtube-media". I'm using the convention of naming the directory name the same as the selector of the component. It makes it easier to spot and find it.

From this point, in this article, i'll refer to Echoes angular1 with ES2015 as "echoes1", while referring to the new angular2 conversion, "echoes2".

File Naming

In echoes1, i'm using these file naming for the youtube-media component:

  • index.js
  • youtube.media.less
  • youtube.media.tpl.html

Note: This is in contrary to other components, where I use the "kebab" notation / dash (meaning, I should change that in echoes1 as well).

In echoes2, I  updated the files:

  • youtube-media.ts (former: index.js)
  • youtube-media.less
  • youtueb-media.html

I find it easier to maintain and spot the youtube-media.ts file in my code editor, other than using just plain "index.js". Also note, I'm using the "ts" extension now for "typescript" files rather than "js" for ES2015 javascript.

I decided to drop the "tpl" postfix, since in 99% of cases, the project uses "html" extension for templates.

Defining angular 2 Component for YoutubeMedia

In echoes1, the index.js imports only the template file, where the other component definitions are objects and functions.

In echoes2, the story is different.

First, I import the necessary annotations and directives that the component will use:

Component Definition

Second, I have to define the component's properties.

In echoes1, a plain object is used:

I'm not actually using the "selector" property, but rather using it when defining the directive.

In echoes2, this definition is shorter:

Notice that the "scope" attributes have been divided to its proper definition properties: 'media' is expected to be passed as a binding from outside. The events that this component expose are: 'play', 'queue' and 'add'.

Controller/Class Definition

In echoes1, the controller is as:

In echoes2, the controller is a class and it's exported. The default properties are defined and initiated in the class definition.

The "video" property with the "@Input()" annotation is optionally defined here (just to make a point). This definition can be either instead of the "inputs" array in the component definition. However, defining it here with the correct type, will aid if the code editor is content aware and supports Typescript parsing. The same goes for the events that are defined with "EventEmitter".

In angular2, access to the external bind property "media", can be accessed in "ngOnInit" hook method (ng2 terminology) rather than in the constructor. The 2 string properties, likeCount and viewCount are converted to numbers, so it can be formatted later in the template using angular 2 pipes (the equivalent to angular 1 filters).

Template Conversion

In echoes1, the template is (I dropped the social share feature for now):


This is the template for echoes2:

There few noticeable changes that needs to be made:

Change the one-time binding prefixed with "::" to be without it.

Handling the "controllerAs: '$ctrl'" - either remove it or creating an alias on the ng2 class - this can be easily made with a simple

but, I decided to drop it.

Handling events with the new brackets syntax - "ng-click" is converted to "(click)".

For ng-class, since I imported the NgClass directive in the component, there are 2 ways to it:

  1. Class binding - [class.the-name-of-class]="expression-should-return-boolean"
  2. Using NgClass directive - [ngClass]="{ the-name-of-class: boolean-experssion }".

By Angular 2 ngClass docs, for 1 class binding, the 1st method  (class binding) is preferred.

The last change is formatting numbers with filters in angular 2. There's a new syntax for filters in angular 2. Filters are now Pipes. The "Number" pipe (ng1 filter: number) should be used with the "DecimalPipe",  in order to format a number with commas. it should be defined as:

The format must be defined with the appropriate digits - I followed the exact instructions in angular2 docs to understand and define each digit.

Using youtube-media angular 2 component

In echoes1, the youtube-media component is used as:

In echoes2, we can use the new component in echoes2 as such:

Final Thoughts

My overall experience is quite good. This "small" migration process went well enough - and still - a lot of work and exploration is left to complete the full Echoes app.

You can overview the complete code on github - you can watch the issues for any progress on a specific component, service or other. As I stated in the beginning of this article, I intend to write a series of articles about the migration process of Echoes Player from angular 1 to angular 2.

I like how the component's code is very concise in its meaning, quite readable and comes with error notification support (I use sublimetext with the typescript package). Also, the new template syntax is great and promotes readability.