Write Angular 2 Components In Angular 1

Angular 2 is a new take to the web components approach. It introduced a quite different syntax with the addition of typescript, annotations and more. Eventually, it has to be compiled to javascript, so the non-javascript syntax is transformed into plain ES5 code. After reading a post about better ES5 code for angular 2, the idea of experimenting with this syntax in angular 1 can be beneficial for future migration, for learning the new syntax, and perhaps, minimising the code written with angular 1.

Preface: The Echoes Project

Echoes is an open source project that i’ve recently converted to angular 1. Essentially, It is a media player aims to deliver a great user experience in listening and watching videos from youtube. It also serves as a code playground for experimenting with various solutions.

Echoes is composed of several modules. I like the modular approach, which is described nicely with the concept of web components. I wrote before about how I see and integrate this approach in some of the modules in Echoes.

The Youtube Videos Module (Web Component)

The first impression in Echoes is the youtube videos results grid (the area of the thumbnails):

youtube-videos is an angular module. It consumes 2 core services:

  1. echoes-services — which includes access to various youtube api, various core resources.
  2. youtube-player — a module which displays the youtube player and exposes a service to interact with.

As I wrote before, in order to use this module, I exposed it a directive, and can simply use it like so:

<youtube-videos></youtube-videos>

Angular 1 Directive Definition

In order to user youtube-videos module as a direcive, I defined it as a quite simple directive with this code:

(function(){
‘use strict’;
angular
  .module(‘youtube.videos’)
  .directive(‘youtubeVideos’,youtubeVideos);
function youtubeVideos(){
  var directive = {
    templateUrl:’app/youtube-videos/youtube.videos.tpl.html’,
    controller:’YoutubeVideosCtrl’,
    controllerAs:’vm’,
    restrict:’E’,
    replace:true
};
  return directive;
})();

Although, the code is quite minimal, during time, I thought that it can be defined better — better to readability and for writing less code.

After reading Pascal Precht ʕ•̫͡•ʔ post “Even better ES5 code for Angular 2“, I was quite happy to find out that syntactical improvements for ES5 have been integrated to the latest alpha version of angular 2. These improvments goes back to a more minimal code defintion in angular 2, while not having the need for annotations or a more complex code for creating an “annotation” object for each purpose.

Angular 2 Component with Angular 1

Following Pascal’s post, I saw a great opportunity to try embracing angular’s 2 component approach and syntax to my youtube-videos module.

First, I read through to understand how I can transform the defintion of the directive to component in angular 2. I came up with this new syntax for angular 1 approach for defining a module as a directive or a component based on the latest angular 2 ES5 syntax:

angular
.Component({
  selector:’youtube-videos’,
  appInjector:[
    ‘echoes.services’,
    ‘youtube.player’
.View({
    templateUrl:’app/youtube-videos/youtube.videos.tpl.html’
.Class({
    constructor:’YoutubeVideosCtrl’
})

The code above works seamlessly the same of the angular 1 directive code, that with a little shim that I wrote which should be loaded right after angular.

<script type=”text/javascript”src=”../bower_components/angular/angular.js”></script>
<script type=”text/javascript”src=”../node_modules/angular2to1/index.js”></script>

angular2to1 is published as an npm module. to install it, simply use npm:

angular2to1 Assumptions

Since the angular2to1 shim is in early stages, I have taken few assumtptions with it:

  1. a component is an element by default — unless the “selector” defines it as an attribute
  2. Currently, it supports an element and an attribute (no support for nested selectors, class selectors and multiple selectors)
  3. the resulted directive definition always use: “controller as vm”
  4. “bindToController” is always true (currently)
  5. Each components is defined with a private scope (scope: {}) by default (can be changed)
  6. template syntax is still angular 1 (that’s why I currently prefer currently to use the templateUrl property”
  7. the ‘appInjector’ currently uses strings rather than objects (which defers form angular 2)
  8. “constructor” in Class annotation, can be a reference to an actual function (rather than a string)
  9. the custom element is not “replaced” after render — so actually, the “replace” property of angular 1 directive is false by default (it can be changed, see below).

Also important to note that the angular.Component defintion returns an object which exposes the directive definition object:

var myAppComponent = angular.Component({
  selector:’my-app’
  appInjector:[
    ‘core.services’
]});
// _directive object is accessible to add or change angular 1 directive properties
console.log(myAppComponent._directive);

This allows you to still be able to define angular 1 directive properties (such as “replace: true” for templates and the directive element).

Pros

Though the angular2to1 shim is far from complete and is lack with many other features of angular 2, there are few pros for using it:

  1. I can experiment with angular 2 ES5 syntax right now with angular 1
  2. I can learn angular 2 concepts while working with angular 1
  3. When migration time to angular 2 comes, it might ease the process — in which I’d like to explain in depth below.

Easing the Migration Process to Angular 2

I realize the migration depends on other factors as well. However, taking few steps with angular 1 today might ease migration later.

Embracing the CommonJs module approach — with browserify (as described by Ben Clinckinbeard) or webpack), takes the code to plain javascript functions that can be used regardless the framework you use.

Using the “controllerAs” enhancements (along with bindToController) directs to write the resulted code of the controller as javascript function, agnostic to any other angular or framework.

Keeping the definition of the component in a separate file (or following Ben’s slide to work with browserifiy) will help in following the separation of concerns.

Conclusion

Regardless angular 2 syntax, in my opinion, this syntax is much nicer, more minimal in it approach and still readable while following conventions (i.e, using selectors to define web components). So, I still my self using it with angular 1.

There is still much work and other nice concepts in angular 2 that I hope to integrate so I can easily use it with angular 1, and hopefully, ease the migration to angular 2 when the time comes.

angular2to1 is open source and hosted on github. Please, feel free to support it, open issues and help to extend it.


Originally published at orizens.com on July 10, 2015.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.