Friday, 25 December, 2015 UTC


Summary

Now that Angular 2 is in beta someone moved our cheese! Let’s put on our running shoes. I have been writing Angular 2 for nearly one year now (actually, since this tweet) and I want to share what I quickly discovered in that time. We are going to see that everything’s changed but nothing is different. This is the Angular you have been looking for.
For this article when I refer to AngularJS I’m speaking about Angular 1.x and Angular as both frameworks
ES2015 was previously known as ES6
TypeScript is ES2015 + Optional Types
Bootstrapping
Both AngularJS and Angular 2 can be used with normal ES5, but most folks should be using use ES2015 with AngularJS and with Angular 2 it is highly recommended to use TypeScript.
It’s worth noting that our browsers today currently varies when it comes to ES2015 features that are implemented. Neither technologies (ES2015 or TypeScript) can run natively in any browser (perhaps TypeScript with Edge browesr). We must have a solid build step to transform our code into ES5 for cross platform support. Webpack and/or Gulp are the popular choices for the bundling and building our application code. Once you have your preferred build process we can bootstrap our application. If you’re in a hurry and just wanna get started, check out our Angular 2 Webpack Starter and NG6-starter (AngularJS) on github.

AngularJS

<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
  <app>
    Loading...
  </app>
  <script src="bundle.js"></script>
</body>
</html>

Angular 2

<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
  <app>
    Loading...
  </app>
  <script src="bundle.js"></script>
</body>
</html>
Our templates remain the same since we are also using the component pattern in AngularJS we are attaching our behavior to the <app> html element for our simple hello world component. With component driven architecture we compose our behavior by encapsulating them in a declarative way, in this case, our application.

AngularJS

npm install core-js // polyfills
npm install angular // app
// Polyfills
import 'core-js';
// AngularJS
import angular, {bootstrap} from 'angular';

angular.module('app', [ ])
.component('app', {
  restrict: 'E',
  template: `<div>hello world</div>`,
  controller: class App {}
});

bootstrap(document, ['app']);

Angular 2

npm install zone.js es6-shim es6-promise es7-reflect-metadata // polyfills
npm install angular2 // app
// polyfills 
import 'es6-shim';
import 'es6-promise';
import 'es7-reflect-metadata/dist/browser';
import 'zone.js/lib/browser/zone-microtask';
import 'zone.js/lib/browser/long-stack-trace-zone';
// Angular 2
import {bootstrap} from 'angular2/platform/browser';
import {Component} from 'angular2/core';

@Component({
  selector: 'app',
  template: `<div>Hello World</div>`
})
class App {}

bootstrap(App, []);
The first thing you notice are the list of polyfills necessary for Angular 2.
* core-js: a highly modular suite of each ES2015 polyfills
* es6-shim: a shim to ensure most ES2015 features work in any browser
* es6-promise: a polyfill for native Promise
* es7-reflect-metadata: a polyfill for typescript to emit typed data in a constructor of a class (more on this later)
* zone.js/lib/browser/zone-microtask: a way for JavaScript developers to keep track of our browser’s VirtualMachine
* zone.js/lib/browser/zone-microtask: enable longer stack trace from asynchronous calls. One of the many features for using zone.js
With both versions of Angular we are importing our bootstrap function that will wire up dependency injection for our application.

AngularJS

import angular, {bootstrap} from 'angular';

Angular 2

import {bootstrap} from 'angular2/platform/browser';
import {Component} from 'angular2/core';
The difference here is that with AngularJS the framework is assuming that we are working in the browser. With Angular 2 we can run JavaScript not only in our browsers but in other environments such as the server or in a webworker.

AngularJS

angular.module('app', [ ])
.component('app', {
  restrict: 'E',
  template: `
hello world
`, controller: class App {} });

Angular 2

import {bootstrap} from 'angular2/platform/browser';
import {Component} from 'angular2/core';
It seems like Angular 2 is taking more advantage of new features provided by ES2015 while AngularJS had to create it’s own abstraction to deal with modules. Notice how both versions of Angular we are providing metadata for Angular’s compiler the difference is how the framework handle our metadata. With Angular 2 we are attaching the metadata to our App class allowing us to pass around App while AngularJS we need to define our metadata within the angular.module abstraction. It’s also worth noting that Angular 2 makes use of decorators use @ a lot.
Decorators
We can think of decorators as a function that changes the behavior of our classes.
function readonly(component) {
  component.writable = false;
  return component;
}

@readonly
class App {

}
In the example above we can attach properties and in this case we added writable. If we want to configure which properties we add which how change the behavior then we return a function.
function configMyDecorator(config) {

  function myAttachDecorator(component) {
    component.writable = config.writable;
    return component;
  }

  return myAttachDecorator;
}


@configMyDecorator({
  writable: false
})
class App {}
we can also use configMyDecorator without the @ syntax.
class App {}
configMyDecorator({
  writable: false
})(App);
So Angular 2 makes use of these decorators to attach metadata to our components which are classes.
Storing state
Modern web development is all about managing state of our applications. In this example we’re going to simplify state management by going over local state within our view. We’re talking more about view state that lives within the component which can also be called ViewModel since it’s a model that only lives for our view.
AngularJS
angular.module('app', [ ])
.component('app', {
  restrict: 'E',
  template: `
{{ app.myState }}
`, controller: class App { constructor() { this.myState = 'California'; } } });

Angular 2

@Component({
  selector: 'app',
  template: `<div>{{ myState }}</div>`
})
class App {
  myState = 'California';
}
TypeScript allows us to define initial state 'California' of our properties myState within the class App as syntactic sugar. Normally we have to manually write out the value inside our constructor as we did with AngularJS. If we use TypeScript with AngularJS then conceptually nothing has changed other than writing half the code.
Event handlers
AngularJS allows us to declaratively register a listen to elements in our DOM to actions, methods that live in the current scope.

AngularJS

angular.module('app', [ ])
.component('app', {
  restrict: 'E',
  template: `Action`,
  controller: class App {
    action(e) {
      console.log("never going to give you up", e);
    }
  }
});

Angular 2

@Component({
  selector: 'app',
  template: `<button on-click="action($event)">Action</button>`
})
class App {
  action(e) {
    console.log("never going to let you down", e);
  }
}
The only thing different here is the way we register our listener for our action. With AngularJS the framework provided us with a set of core directives for each native event but we found out that doesn’t scale well when we have to deal with custom events. With Angular 2 being able to register a listener for any event was preferred over reusing the directive api we use the on-(event name) (for example, on-submit, on-input, and on-change). Angular 2 allows us to also register an event for our element with a shorthand syntax which is the preferred syntax and one that I recommend.

Angular 2

@Component({
  selector: 'app',
  template: `<button (click)="action($event)">Action</button>`
})
class App {
  action(e) {
    console.log("I'm never gonna walk away", e);
  }
}
For example, (submit), (input), and (change) are used. The shorthand syntax allows us to quickly scan our templates for all events rather than guessing what the event might be of a random 3rd party directive. We can think of this approach from another perspective and that’s how we do it natively in our browser.

Native Browser

<button id="myButton" onclick="action()">Action</button>
<script>
  function action(e) {
    console.log("I'm always gonna have your back", e);
  }
  // we have a reference to our button because of id="myButton"
  // to emit the click event we simply invoke the native method
  window.myButton.click();
</script>
We are invoking the click event with the method click() so our shorthand syntax uses the same () to show us the event (click) will be invoked as (click)="action()". On (click) invoke action() or on-click="action()".
Change Detection
In AngularJS we were introduced to the $digest loop which may have caused some confusion as to why it should be invoked. In Angular 2 we have been told that we no longer need to invoke the $digest loop anymore because of the magic from zone.js.
As a refresher the $digest loop is run whenever we want to reflect the changes of our ViewModels to the screen. So any data that are glue to our view with bindings{{ text }} will be checked if they have changed and we got the concept from game design. We use dirty checking as an optimization for when we change the value of our ViewModel many times before we want to render it rather than rendering the view each time the view changed.

AngularJS

angular.module('home', [ ])
.component('home', {
  restrict: 'E',
  template: `
  <button ng-click="home.getData()">Get Server Data</button>
  <code><pre>{{ home.text }}</pre></code>
  `,
  controller: class Home {
    constructor($rootScope) {
      this.$rootScope = $rootScope;
      this.text = {};
    }
    getData(e) {
      // ajax  
      setTimeout(() => {
        // async callback
        // change the value of our ViewModel
        this.text = {res: 'something else'};
        this.text = {res: 'data'};
        this.$rootScope.$digest(); // something changed
      }, 1000);
      //
      // $digest() ran by ng-click
    }
  }
});

Angular 2

@Component({
  selector: 'home',
  template: `
  <button (click)="getData()">Get Server Data</button>
  <code><pre>{{ text }}</pre></code>
  `
})
class Home {
  text = {};
  getData(e) {
    // ajax  
    setTimeout(() => {
      // async callback
      this.text = {res: 'something else'};
      this.text = {res: 'data'};
      // zone.js tells triggers
    }, 1000);
  }
}
With AngularJS these $digest calls were hidden from us with the core directives such as ng-click which runs the $digest loop after it invokes our action. The problem that everyone runs into is when we do something asynchronous. In our AngularJS example we had to manually tell Angular to reflect our changes since the core directive ng-click already ran. With Angular 2 we have zone.js which will tell us when all the async calls within a given scope are done so we don’t have to Angular to trigger Change Detection. Actually if you forget to include zone.js we will have the same problem as we did in AngularJS where we have to manually trigger Change Detection for a component. If you want to understand zone.js more here’s a video of Miško Hevery explaining it.
Dependency Injection
In AngularJS we have an amazing feature called Dependency Injection that allowed us not to worry about creating our dependencies in the correct order. We were inverting control over to the framework and following a certain convention. As a refresher we can think of Dependency Injection simply as a huge key value store.
var di = {};

function MyService() {
  console.log("I'm at your service");
}
MyService.$inject = [];

var app = {
  Home: [ 'MyService', function(myservice) {
    console.log("I'm Home Component", myservice);
  }]
}

// during bootstrap
di['MyService'] = new MyService();

var controller = app.Home.pop();
var tokens = app.Home; // now just an array without the function;

var args = tokens.map(function(token) {
  return di[token];
});
// remember .apply(context, arguments) is JavaScript way of calling a function within another context as well as providing arguments as an array
controller.apply(controller, args);
There are some limitations here since the key, as we know in JavaScript Object Literal, can only be a string in ES5. With Angular 2 we use the Map which allows us to use anything as the key and the most common use case would be the provider itself as the token.
class Service {
  constructor() {
    console.log('hello from service');
  }
}

var di = new Map();

var instance = new Service();

di.set(Service, instance);

di.get(Service); // returns instance
Angular 2 makes use of this and uses the reference to the class itself to represent the instance.
Services/Providers/Factory/Value/Constant?
AngularJS we had many different ways to create Services which were all Providers at the end of the day. In Angular 2 we changed the name of .service and removed .constant but we mostly will be using what we called .service in AngularJS. In both versions of Angular we can call them providers.

AngularJS

angular.module('home', [ ])
.service('Service', class Service {
  constructor() {
    this._data = [];
  }
  getData() {
    return this._data;
  }
})
.component('home', {
  restrict: 'E',
  template: `<code><pre>{{ home.service.getData() }}</pre></code>`,
  controller: class Home {
    constructor(Service) {
      this.service = Service;
    }
  }
});

Angular 2

@Injectable()
class Service {
  _data = [];
  constructor() {
    
  }
  
  getData() {
    return this._data;
  }
}

@Component({
  selector: 'home',
  providers: [ Service ]
  template: `<code><pre>{{ service.getData() }}</pre></code>`
})
class Home {
  // we are using TypeScript 'public' modifier
  constructor(public service: Service) {
  
  }
}
We are using a TypeScript feature called a public modifier that will declare our type on our class as well the type of the argument and set to the same property. Previously we got away with not declaring our type information because we were specifying default values of our properties outside our constructor.
class Home {
  service: Service; // declare what instance type each property should be above our constructor
  constructor(service: Service) {
    this.service = service
  }
}
There’s a few things that are new in Angular 2 but conceptually they are the same. With Angular 2 again we have to say what providers Service are in this component Home then we inject our Service using our type Service as the token then we are also using TypeScript’s emitMetadata feature that essentially does what we did with ng-annotate in AngularJS. Let’s rewrite this component in ES5 to see what’s going on.

Angular 2

var Service = ng.
 Injectable().
 Class({
  constructor: [function() {
    this._data = [];
  }],
  getData: function() {
    return this._data;
  }
});

var Home = ng.
  Component({
    selector: 'home',
    providers: [ Service ]
    template: '<code><pre>{{ service.getData() }}</pre></code>'
  }).
  Class({
  // we are using TypeScript 'public' modifier
  constructor: [Service, function(service) {
    this.service = service
  }]
}
We can see that our constructor takes an array for us to declare what our dependencies are for our component with the last value being our function.
Component composition
With AngularJS we compose our components nearly the same way as we do with Angular 2.

AngularJS

angular.module('app', [ ])
.component('navbar', {
  restrict: 'E',
  template: `
{{ navbar.text }}
`, controller: class Navbar { constructor() { this.text = 'navbar'; } } }) .component('footer', { restrict: 'E', template: `
{{ footer.text }}
`, controller: class Footer { constructor() { this.text = 'footer'; } } }) .component('home', { restrict: 'E', template: `
{{ home.text }}
`, controller: class Home { constructor() { this.text = 'home' } } });

Angular 2

@Component({
  selector: 'navbar',
  template: `<div>{{ text }}</div>`
})
class Navbar {
  text = 'navbar';
}
@Component({
  selector: 'footer',
  template: `<div>{{ text }}</div>`
})
class Footer {
  text = 'footer';
}
@Component({
  selector: 'home',
  directives: [Navbar, Footer],
  template: `
  <navbar></navbar>
  <div>{{ text }}</div>
  <footer></footer>
  `
})
class Home {
  text = 'home';
}
With Angular 2 we have to specify which directives live in our template. That’s because the metadata lives on our component’s which is just a regular JavaScript class. With AngularJS we had a module system that was connected with everything else which allowed us to check globaly if we have the directive. (There are ways to have the same effect in Angular 2 that would provide us with the same workflow but more on that in the next article)
Scope, Bindings, and Properties
AngularJS had an idea of $scope and $rootScope which is the ViewModel to our views. Another way to think of $scope is how our browser works. If you ever tried to run toString() in the console you will see "[object Window]" because our scope currently is window (and window is referncing itself). So when we create a new scope (in this sense)
function Scope() {
}
var scope = new Scope();
scope.toString();
we get "[object Object]" but we can change the value.
function Scope() {
  this.toString = function() {
    return 'oh hai';
  }
}
var scope = new Scope();
scope.toString();
so in our templates the scope becomes the controller in AngularJS and when we use controllerAs syntax we are doing the same as window.toString(). We did this because it is really hard to see what the scope is when we’re dealing with many scopes within a template.
<div ng-controller="top">
  {{ prop }}
  <div ng-controller="middle">
    {{ prop }}
    <div ng-controller="bottom">
      {{ prop }}
    </div>
  </div>
</div>
in the template above it’s really hard to tell where the value of prop is coming from within these scopes. When we switched to controlerAs to solve this.
<div ng-controller="top as vm">
  {{ vm.prop }}
  <div ng-controller="middle as vm">
    {{ vm.prop }}
    <div ng-controller="bottom as vm">
      {{ vm.prop }}
    </div>
  </div>
</div>
Wait, we still have the same problem so why are we calling everything vm thinking it will solve our problems
<div ng-controller="top">
  {{ top.prop }}
  <div ng-controller="middle">
    {{ middle.prop }}
    <div ng-controller="bottom">
      {{ bottom.prop }}
    </div>
  </div>
</div>
Correctly naming our controller to make it very clear as to what is referncing what value. There is a term for this and it’s called refernceal transparentcy which means it’s very transparent to know what our refernces are. We can also mix references and still be able to quickly reason about where the value is coming from since the refernces of values for each scope is very clear.
<div ng-controller="top">
  {{ top.prop }}
  <div ng-controller="middle">
    {{ top.prop }}
    {{ middle.prop }}
    <div ng-controller="bottom">
      {{ top.prop }}
      {{ middle.prop }}
      {{ bottom.prop }}
    </div>
  </div>
</div>
AngularJS also provides us with a way to oraganize our code so we won’t have to deal with thinking about many scopes. We do this by creating a .component which will create a new scope for our code to live in. We also make sure that logic that is only concerned with that part of the view only lives in that component.
angular.module('app', [ ])
.component('bottom', {
  restrict: 'E',
  bindings: {
    top: '=',
    middle: '='
  },
  template: `
  {{ top.prop }}
  {{ middle.prop }}
  {{ prop }}
  `,
  controller: class Bottom {
    constructor() {
      this.prop = 'bottom';
    }
  }
})
.component('middle', {
  restrict: 'E',
  bindings: {
    top: '='
  },
  template: `<bottom top="middle.top" middle="middle"></bottom>`,
  controller: class Middle {
    constructor() {
      this.prop = 'middle';
    }
  }
})
.component('top', {
  restrict: 'E',
  template: `
  <middle top="top"></middle>
  `,
  controller: class Top {
    constructor() {
      this.prop = 'top'
    }
  }
});
With this AngularJS example we can separate our view logic within the correct component. Doing so allows us to lower the amount of mental overhead of the state of our application since we only need to worry about the current component and the data that’s coming in. With Angular 2 let’s go over how we compose our components.
@Component({
  selector: 'bottom',
  template: `
  {{ prop }}
  `
})
class Bottom {
  prop = 'bottom';
}
@Component({
  selector: 'middle',
  directives: [ Bottom ],
  template: `
  <bottom></bottom>
  {{ prop }}
  `
})
class Middle {
  prop = 'middle';
}
@Component({
  selector: 'top',
  directives: [ Middle ],
  template: `
  <middle></middle>
  {{ prop }}
  `
})
class Top {
  prop = 'top';
}
We can clearly see what the prop is for each component because we’re not viewing all of the components at the same time. So then how do we pass values around from parent components? We do it by specifying our Input values
@Component({
  selector: 'bottom',
  inputs: [
   'topProp',
   'middleProp'
  ],
  template: `
  {{ topProp }}
  {{ middleProp }}
  {{ prop }}
  `
})
class Bottom {
  topProp = '';
  middleProp = '';
  prop = 'bottom';
}

@Component({
  selector: 'middle',
  directives: [Bottom],
  inputs: [
    'topProp'
  ],
  template: `
  <bottom [topProp]="topProp" [middleProp]="prop" ></bottom>
  {{ topProp }}
  {{ prop }}
  `
})
class Middle {
  top = '';
  prop = 'prop';
}
@Component({
  selector: 'top',
  directives: [Middle],
  template: `
  <middle [topProp]="prop"></middle>
  {{ prop }}
  `
})
class Top {
  prop = 'top';
}
What we’re doing is creating a new scope with each new component and remember that our scope is the component itself. For example
var top = new Top();
var middle = new Middle();
var bottom = new Bottom();
And how would we dynamically set the properties of an instance in JavaScript? With the bracket notation.
var top = new Top();

var middle = new Middle();
middle['topProp'] = top.prop;

var bottom = new Bottom();
bottom['topProp'] = middle.topProp;
bottom['middleProp'] = middle.prop;
So when we see the syntax <bottom [topProp]="topProp"></bottom> it’s simular to how we do it in JavaScript as bottom['topProp'] = middle.topProp; We also also use another syntax which is the prefered and recommended version using the @Input() decorator.
@Component({
  selector: 'bottom',
  template: `
  {{ topProp }}
  {{ middleProp }}
  {{ prop }}
  `
})
class Bottom {
  @Input() topProp = '';
  @Input() middleProp = '';
  prop = 'bottom';
}

@Component({
  selector: 'middle',
  directives: [Bottom],
  template: `
  <bottom [topProp]="topProp" [middleProp]="prop" ></bottom>
  {{ topProp }}
  {{ prop }}
  `
})
class Middle {
  @Input() topProp = '';
  prop = 'prop';
}
@Component({
  selector: 'top',
  directives: [Middle],
  template: `
  <middle [topProp]="prop"></middle>
  {{ prop }}
  `
})
class Top {
  prop = 'top';
}
Data Binding
One of the biggest differences between the two frameworks is data binding. In AngularJS the default is two-way with an option to use one-way-one-time. With Angular 2 we have one-way binding but we have directives that can help with two-way data binding. It turns out that we only need two-way data binding for forms while everywhere else usually remains static.

AngularJS

angular.module('app', [ ])
.component('middle', {
  restrict: 'E',
  bindings: {
    top: '='
  },
  template: `
   {{ top.prop }} 
   change
  `,
  controller: class Middle {
    changeData() {
      this.top.prop = 'somethingNew';
    }
  }
})
.component('top', {
  restrict: 'E',
  template: `
  
  {{ top.prop }}
  `,
  controller: class Top {
    constructor() {
      this.prop = 'top'
    }
  }
});

Angular 2

@Component({
  selector: 'middle',
  template: `
  {{ topProp }}
  <button (click)="changeData()">change</button>
  `
})
class Middle {
  @Input() topProp = '';
  
  changeData() {
    this.topProp = 'somethingNew';
  }
}
@Component({
  selector: 'top',
  directives: [Middle],
  template: `
  <middle [topProp]="prop"></middle>
  {{ prop }}
  `
})
class Top {
  prop = 'top';
}
In Angular 2 when we invoke changeData() we are able to see the value changed only for Middle component not in Top component. This is due to one-way data flow where we get the initial state from the top-level-components to be passed down to child components. Doing so gives us faster Change Detection since we’re able to optimise which components should be updated and which ones should not. While in AngularJS we can see that data is being reflected in both components because of two-way data binding. We can update our parent component by emitting events from our child components. We can do this by hooking into native events that bubble up
@Component({
  selector: 'middle',
  template: `
  {{ topProp }}
  <button>change</button>
  `
})
class Middle {
  @Input() topProp = '';
}
@Component({
  selector: 'top',
  directives: [Middle],
  template: `
  <middle [topProp]="prop" (click)="changeData()"></middle>
  {{ prop }}
  `
})
class Top {
  prop = 'top';
  changeData() {
    this.topProp = 'somethingNew';
  }
}
Now when we click on our button we are invoking changeData() in the top-level-component Top where the state is being stored. This is called unidirectional-way data flow where data in our view flows one way. We can also use providers to store and update our data.
// function that does nothing when invoked
function noop {}

@Injectable()
class Service {
  _data = {};
  _updateCallback = noop;
  getLatest() {
    return this._data;
  }
  onUpdate(callback) {
    this._updateCallback = callback;
  }
  update(value) {
    this._data = value; // set current value
    this._updateCallback(this._data); // invoke current update function
  }
}

@Component({
  selector: 'middle',
  template: `
  {{ topProp }}
  <button>change</button>
  `
})
class Middle {
  @Input() topProp = '';
  constructor(public service: Service) {

  }
  
  changeData() {
    var newData = 'somethingNew';
    this.service.update(newData)
  }
}
@Component({
  selector: 'top',
  directives: [ Middle ],
  providers: [ Service ],
  template: `
  <middle [topProp]="prop" (click)="changeData()"></middle>
  {{ prop }}
  `
})
class Top {
  prop = '';
  constructor(public service: Service) {
    // We want to update our ViewModel
    this.service.onUpdate(data => {
      this.prop = data;
    });
    this.service.update('top');
  }

}
In this example we are resgistering a callback on our Service with onUpdate then updating our initial view with "top". The problem here is that we’re going to end up recreating an EventEmitter within our service if we continue down this path. This is why an EventEmitter becomes baked into Angular 2 and in fact not just any EventEmitter it’s it’s Observables which is an ES7 spec. Let’s refactor our example to use an Observable first.
import {Observable} from 'rxjs/Rx';

@Injectable()
class Service {
  _data = {};
  observar = new Observable();
  getLatest() {
    return this._data;
  }
  update(value) {
    this._data = value;
    // `.next()` means the next state in our stream
    this.observar.next(this._data);
  }
}

@Component({
  selector: 'middle',
  template: `
  {{ topProp }}
  <button (click)="changeData()">change</button>
  `
})
class Middle {
  @Input() topProp = '';
  constructor(public service: Service) {

  }
  
  changeData() {
    var newData = 'somethingNew';
    this.service.update(newData)
  }
}
@Component({
  selector: 'top',
  directives: [ Middle ],
  providers: [ Service ],
  template: `
  <middle [topProp]="prop" (click)="changeData()"></middle>
  {{ prop }}
  `
})
class Top {
  prop = '';
  constructor(public service: Service) {
    // We want to update our ViewModel
    this.service.observar.subscribe(data => {
      this.prop = data;
    });
    this.service.update('top');
  }

}
Great so now we’re using a new ES7 feature but we can use the EventEmitter provided by Angular which uses rxjs‘s Subject and Angular 2’s @Output decorator.
@Injectable()
class Service {
  _data = {};
  getLatest() {
    return this._data;
  }
  update(value) {
    return this._data = value;
  }
}

@Component({
  selector: 'middle',
  template: `
  {{ topProp }}
  <button (click)="changeData($event)">change</button>
  `
})
class Middle {
  @Input() topProp = '';
  @Output() update = new EventEmitter();
  changeData($event) {
    this.update.next('somethingNew');
  }
}
@Component({
  selector: 'top',
  directives: [ Middle ],
  providers: [ Service ],
  template: `
  <middle [topProp]="prop" (update)="changeData($event)"></middle>
  {{ prop }}
  `
})
class Top {
  prop = '';
  constructor(public service: Service) {
    this.service.update('top');
  }
  changeData(data) {
    this.service.update(data); // update our state
    this.prop = this.service.getLatest(); // update our ViewModel
  }
  

}
This is great, we’re able to create a custom event using our EventEmitter instance and passing a new value to it using .next() then receiving our data with the $event local variable. Then we’re invoking changeData in our top-level-component to update our service and view. If you’re asking “can we make it more simple?” then I’ll have to answer yes we can. Let’s refactor again.
@Injectable()
class Service {
  _data = {};
  getLatest() {
    return this._data;
  }
  update(value) {
    return this._data = value;
  }
}

@Component({
  selector: 'middle',
  template: `
  {{ topProp }}
  <button (click)="update.next('somethingNew')">change</button>
  `
})
class Middle {
  @Input() topProp = '';
  @Output() update = new EventEmitter();

}
@Component({
  selector: 'top',
  directives: [ Middle ],
  providers: [ Service ],
  template: `
  <middle [topProp]="prop" (update)="prop = service.update($event)"></middle>
  {{ prop }}
  `
})
class Top {
  prop = this.service.update('top');
  constructor(public service: Service) {
  
  }
}
There are many different ways we can update our view now that we have more control. We can completely change the way Angular detects change to fit our needs. Unless AngularJS where we had to control our two-way data flow in Angular 2 it’s simpler to deal with data.
Forms
One of the best things about Angular was two-way data binding with forms. It turns out we want state to persist on the page and not update our models until our customer is ready to save it. With Angular 2 we have form directives to give us our ng-model.

AngularJS

angular.module('home', [ ])
.component('home', {
  restrict: 'E',
  template: `
  <input ng-model="home.text">
  <code><pre>{{ home.text }}</pre></code>
  `,
  controller: class Home {
    constructor() {
      this.text = '';
    }
  }
});

Angular 2

@Component({
  selector: 'home',
  directives: [ FORM_DIRECTIVES ],
  template: `
  <input [(ngModel)]="text">
  <code><pre>{{ text }}</pre></code>
  `
})
class Home {
  text = '';
}
There are really two things to take notice here it’s the [(ngModel)] and FORM_DIRECTIVES. FORM_DIRECTIVES is an array of directives nothing more nothing less.
var FORM_DIRECTIVES = [
  // ... other directives
  NgModel
  // ... other directives
];
Rather than including the name of our angular.module in Angular 2 we just use an array. The next thing is [(ngModel)]. It turns out data-binding is both get data and set data so let’s look at another example.
@Component({
  selector: 'home',
  template: `
  <input [value]="text" (input)="text = $event.target.value">
  <code><pre>{{ text }}</pre></code>
  `
})
class Home {
  text = '';
}
For our <input> tag we are both setting value as text properties and in the event input event we are setting the property test to the value of the event object. For more information about forms we will cover them in our next post.
Dynamic elements
In both versions of Angular we have core directives that change the structure of our views. In Angular 2 we call them Structural Directive.

AngularJS

angular.module('app', [ ])
.component('sidebar', {
  restrict: 'E',
  bindings: {
    title: '=',
    items: '='
  },
  template: `
    
{{ sidebar.title }}
  • {{ item }}
`, controller: class Home { } }); .component('app', { restrict: 'E', template: `
`, controller: class App { constructor() { this.state = { title: 'Side bar', items: ['home', 'profile', 'settings'] }; } } });

Angular 2

@Component({
  selector: 'sidebar',
  template: `
    <div class="sidebar">
      <h1>{{ title }}</h1>
      <ul>
        <li *ngFor="#item of items">
          {{ item }}
        </li>
      </ul>
    </div>
  `
})
class Sidebar {
  @Input() title = '';
  @Input() items = [];
}
 
@Component({
  selector: 'app',
  directives: [
    Sidebar
  ],
  template: `
    <div>
      <sidebar
        [title]="state.title"
        [items]="state.items"
      ></sidebar>
    </div>
  `,
})
class App {
  state = {
    title: 'Side bar',
    items: ['home', 'profile', 'settings']
  };
}
Like AngularJS, Angular 2 has a directive we can use to repeat over data and create elements. The ngFor directive is similar to ng-repeat. Because Angular 2 uses <template> to clone element, for performance reasons, they created a shorthand to expand micro-syntax with *. That’s why we use *ngFor. We are also using refs (references) with the # followed by a variable name to create a local variable in the template to get access to our raw DOM node. We can reason about why the Angular Team choose #. Including an id attribute to an element gives us access to that element globally in our browser. We can get a reference to our div (<div id="myElement"></div>) with window.myElement (if you didn’t know about this then you should try it out). Like ES2015 iterators, we are using a for of loop to iterate over the collection, assigning the current element to the local variable we created.
<div class="sidebar">
  <h1>{{ title }}</h1>
    <ul>
      <template ngFor #item [ngForOf]="items">
        <li>{{ item }}</li>
      </template>
    </ul>
 </div>
Styles
There are many ways to add styles to our components. With build tools like webpack, that lists grows longer and longer. Having css encapsulation is an important part of creating flexible components since it decouples our component from the application as a whole. These styles are scoped to our component using unique class-name to avoid collision baked in.
@Component({
  selector: 'app',
  // encapsulation: ViewEncapsulation.Emulated, // our default setting
  styles: [`
    .app {
      
    }
    .actions {
      
    }
    .button {
      
    }
  `],
  template: `
    <div class="app">
      <div class="actions">
        <button class="button">click</button>
      </div>
    </div>
  `,
})
class App {}
With styles we didn’t have anything in AngularJS but now we do in Angular 2 with ShadowDOM emulation. We an configure our component by setting the encapsulation property on the @Component decorator which allows us to change how our styles scoping behaves. First we need to import ViewEncapsulation. There are three values that we could use. The default for components is ViewEncapsulation.Emulated which outputs namespaces of our class next to our styles. ViewEncapsulations.Native uses the Native ShadowDOM (when that is ready). ViewEncapsulation.None removes any style scopping in our components.
Angular 2 for AngularJS developers
Well it turns out that everything’s changed but nothing is different. When AngularJS was released 6+ years ago we didn’t know best practices for directives or patterns that would simplify our workflow. Now we do and now Angular 2 is the same Angular framework that we all know and love. In fact a common pattern that I’m seeing is that Angular 2 seems like twice the framework with half the application code compared to AngularJS. For the most part we can can use the same patterns in Angular 2 in AngularJS which would help us move to Angular 2. Stay tuned for our next post when we dive deeper into Angular 2 and really showing the power and flexibility that our new framework provides. Angular 2 allows us to do more advanced patterns with less code and easier to reason about. If you like to learn more about Angular 2 in the near future please attend one of our workshop or inquire for corporate training.
The post Angular 2 for AngularJS developers appeared first on AngularClass.