Download - Getting ready for Angular 2
GETTING READY FOR
CTO, Rangle.io
Yuri Takhteyev
Some rights reserved - Creative Commons 2.0 by-sa
ANGULAR 2
• A new front end framework inspired by Angular 1.x
• And by other things also
• Now in “alpha”
What is Angular 2?
Image by mtaphotos
The Context• Angular 1.x and it’s challenges
• Components: Web components, React JS
• Reactive programming: ReactJS, Flux, FRP
• ES6 Classes + annotations
• Strong typing: TypeScript, Flow
• ES6 modules
Angular 1’s View Synchronization• Declarative
• Separation between templates and code
• Two-way data binding
• Stateful
• Using nested $scopes
Alternative: Components• ReactJS
• Web components
• Doable with “controller as” and isolated directives
• Business logic goes into services
Alternative: Unidirectional Flow• ReactJS: better performance, procedural, merges HTML and code
• Flux: easier to reason about complex data flow
• Key idea: events instead of state
• Perhaps even better: FRP
What Angular 2 Promises• Still very declarative
• 3 types of directives: components, decorators, templates
• Support for unidirectional data flow
• Three models: stateful, reactive, immutable
• Componentized: no more $digest cycle
• Controllers folded into components
ES6 Classes
class Widget { name; constructor() { name = 'No name'; } setName(newName) { name = newName; } getName() { return name; }}
Component as a Class
class LoginFormComponent { constructor() { }
validate(field, value) { this[field] = value; this.inputIsValid = (!!this.username && !!this.password); }
authenticate(username, password) { // tbd }}
Component Template
Enter username:<input #username name="username" (keyup)="validate('username', username.value)"><br>
Password:<input #password type="password" name="password" (keyup)="validate('password', password.value)"><br>
<button id="login-button" (click)="authenticate" [disabled]="!!inputIsValid">Login</button>
Annotations in ES5
LoginFormComponent.annotate = [ new Component({ selector: 'acme-login-form' }), new View({ templateUrl: 'authenticate.html', })];
In AtScript / TypeScript / ES7*
@Component({ selector: 'acme-login-form'})@View({ templateUrl: 'authenticate.html',})class LoginFormComponent { ...}
Types
class LoginFormComponent { name: string; inputIsValid: boolean; username: string; password: string; ...
validate(field:string, value:string) { ... }
@Injectable
@Injectableclass SomeService { name; constructor() {} setName(newName) { this.name = newName; } getName() { return this.name; }}
Angular 1.x• ES5 has no modules
• Angular 1’s modules do not provide much isolation
• Alternative: CommonJS (easy but synchronous only)
• Alternative: AMD (asynchronous but complicated)
• Neither really solves Angular 1’s module problem
Going Forward• ES6 introduces the concept of module
• Easy
• Asynchronous when you want it to be
• Angular 2 is leveraging it
• Use SystemJS to load ES6 modules today
• TypeScript introduces a few quirks
Using ES6 Modules
import {Injectable} from 'angular2/di';import {Component, View} from ‘angular2/angular2';...export {SomeService, SomeOtherService};
Playground Projects• https://github.com/SekibOmazic/angular2-playground (elaborate, but uses Traceur)
• https://github.com/angular/ts-quickstart (uses TypeScript, but very bare)
Docs• https://angular.io/ (not much there yet)
• https://www.youtube.com/user/ngconfvideos
• http://bit.ly/ngdocs (design docs, go here to deep-dive)
Get Started on ES6 or TypeScript• Babel or Traceur are easiest to get started with
• TypeScript is what you’ll probably end up using eventually
• ES5 ⊆ ES6, so your code is already ES6
• Write your controllers and services as ES6 classes
ES5 Controller
angular.module('myapp') .controller(['authService', function(authService) { var vm = this; vm.authenticate = function(username, password) { authService.authenticate(username, password) .then(function() { // do something }); }; }]);
ES6 Controller
angular.module('myapp') .controller(['authService', class LoginFormComponent { constructor(authService) { this.authService = authService; } authenticate(username, password) { this.authService.authenticate(username, password) .then(() => /* do something */); } }]);
Consider Modules Too
export class LoginFormComponent { constructor(authService) { this.authService = authService; } authenticate(username, password) { this.authService.authenticate(username, password) .then(() => /* do something */); }}
Importing
import {LoginFormComponent} from 'some/path';
angular.module('myapp') .controller(['authService', LoginFormComponent]);
Organize Your Code as Components• Use isolated directives with “Controller as”
• If your controller is written as an ES6 class, you are getting close to Angular 2 controllers.
ES5 “Controller As” Directive
.directive('acme-user', function () { return { restrict: 'E', scope: { nextName: '@' }, bindToController: true, template: ‘...', controllerAs: ‘vm', controller: function() { var vm = this; vm.name = 'Alice'; vm.change = function() { vm.name = vm.nextName; } } };});
ES5 “Controller As” Directive
controller: function() { var vm = this; vm.name = 'Alice'; vm.change = function() { vm.name = vm.nextName; }},
ES6
controller: class AcmeUserComponent { constructor() { this.name = 'Alice'; } change() { this.name = this.nextName; }}
Consider Using the New Router• Angular 1.4 introduces a new router
• It promises to allow use of Angular 1.x and Angular 2 state controllers side by side.
Consider Flux Architecture• Unidirectional data flow can simplify your architecture
• In Angular 2, use of reactive architecture will also speed things up