Angular 2 in comparison with Angular 1
VS
- Intro
- What is Angular (for those who came from the past)?
- Angular 2 key features
- Comparison
Agenda
Comparison Plan
Core features (Architecture)
Directives
Controllers
Services
Modularity
Template syntax
Misc
DISCLAIMER
All code samples will provided on TypeScript (JavaScript strict typed superset) used by Angular 2 development team and recommended for development of Angular 2 applications.
Angular 2 releasead!
INTRO
Angular
So, what is it?
how it's working?
What is all about?
MV*, MVW
AngularJS is a structural framework for dynamic web apps. It lets you use HTML as your template language and lets you extend HTML's syntax to express your application's components clearly and succinctly. Angular's data binding and dependency injection eliminate much of the code you would otherwise have to write. And it all happens within the browser, making it an ideal partner with any server technology.
So, what is it?
- Modules
- Dependency Injection
- Directives
- Scopes
- Controllers
- Services (Factories)
- Template
how it's working?
TWO-Way Data binding
Angular 2
Key Features
LEts The carnage Begins!
PLATFORM
AngularJS
Angular 2
PLATFORM
(function(app) {
var ng = require('@angular/core');
var router = require('@angular/router');
var heroService = require('./hero.service');
var DashboardComponent = (function() {
function DashboardComponent(heroService, router) {
this.heroService = heroService;
this.router = router;
}
DashboardComponent.prototype.ngOnInit = function() {
var _this = this;
this.heroService.getHeroes()
.then(function(heroes) {
return _this.heroes = heroes.slice(1, 5);
});
};
DashboardComponent.prototype.gotoDetail = function(hero) {
var link = ['/detail', hero.id];
this.router.navigate(link);
};
DashboardComponent = __decorate([
ng.core.Component({
selector: 'my-dashboard',
templateUrl: 'app/dashboard.component.html',
styleUrls: ['app/dashboard.component.css']
}),
__metadata('design:paramtypes', [heroService.default, router.Router])
], DashboardComponent);
return DashboardComponent;
}());
exports.DashboardComponent = DashboardComponent;
})(window.app || (window.app = {}));
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import Hero from './hero';
import HeroSerive from './hero.service';
@Component({
selector: 'my-dashboard',
templateUrl: 'app/dashboard.component.html',
styleUrls: ['app/dashboard.component.css']
})
export class DashboardComponent implements OnInit {
heroes: Hero[];
constructor(
private heroService: HeroSerive,
private router: Router
) { }
ngOnInit(): void {
this.heroService.getHeroes()
.then(heroes => this.heroes = heroes.slice(1, 5));
}
gotoDetail(hero: Hero) {
let link = ['/detail', hero.id];
this.router.navigate(link);
}
}
MODularity
AngularJS
Angular 2
- ng (angular core module)
- ngAnimate ngCookies ngAria ngRoute
- ngSanitize etc...
@angular/common
@angular/common/testing
@angular/core
@angular/forms
@angular/http
@angular/router
@angular/platform-browser
@angular/platform-browser-dynamic
@angular/platform-server
@angular/upgrade
@angular/platform-webworker
MODularity
- ES6 import export
- Lazy load
Need to do some magic...
DIRectives
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0,
template: '', // or function
// or
// templateUrl: '', // or function
transclude: false,
restrict: 'A', // E, C, M, AE, CM, etc
templateNamespace: 'html',
scope: false,
controller: function($scope) { ... },
controllerAs: '',
bindToController: false,
require: 'siblingDirectiveName',
multiElement: false,
compile: function () {}
// or
// link: function() {}
};
return directiveDefinitionObject;
});
import { Directive, Input } from '@angular/core';
import { TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({ selector: '[myUnless]' })
export class UnlessDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef
) { }
@Input() set myUnless(condition: boolean) {
if (!condition) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
}
}
CONTROLLERS
AngularJS
Angular 2
var myApp = angular.module('spicyApp2', []);
myApp.controller('SpicyController', ['$scope', function($scope) {
$scope.customSpice = 'wasabi';
$scope.spice = 'very';
$scope.spicy = function(spice) {
$scope.spice = spice;
};
}]);
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import Hero from './hero';
import HeroService from './hero.service';
@Component({
selector: 'my-hero-detail',
templateUrl: 'app/hero-detail.component.html',
styleUrls: ['app/hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit{
hero: Hero;
constructor(
private heroService: HeroService,
private route: ActivatedRoute
) {}
ngOnInit(): void {
this.route.params.forEach((params: Params) => {
let id = + params['id'];
this.heroService.getHero(id)
.then(hero => this.hero = hero);
});
}
goBack(): void {
window.history.back();
}
save(): void {
this.heroService.update(this.hero)
.then(this.goBack);
}
}
DI
AngularJS
Angular 2
// inferred (only works if code not minified/obfuscated)
$injector.invoke(function(serviceA){});
// annotated
function explicit(serviceA) {};
explicit.$inject = ['serviceA'];
$injector.invoke(explicit);
// inline
$injector.invoke(['serviceA', function(serviceA){}]);
// @Injectable()
// class MyService() {}
// providers: [MyService, { provide: ... }]
// constructor(myService: MyService, ...) { ... }
// { provide: MyService, useClass: MyMockService }
// car: Car = this.injector.get(Car);
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import Hero from './hero';
@Injectable()
export default class HeroService {
private heroesUrl = 'app/heroes';
private headers = new Headers({'Content-Type': 'application/json'});
constructor(private http: Http) {
}
//Service logic goes here
}
SERVICEs
AngularJS
Angular 2
var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
var shinyNewServiceInstance;
// factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
app.service('hexafy', function() {
this.myFunc = function (x) {
return x.toString(16);
}
});
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import Hero from './hero';
@Injectable()
export default class HeroService {
private heroesUrl = 'app/heroes';
private headers = new Headers({'Content-Type': 'application/json'});
constructor(private http: Http) {
}
getHeroes(): Promise<Hero[]> {
return this.http.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data as Hero[])
.catch(this.handleError);
}
getHeroesSlowly(): Promise<Hero[]> {
return new Promise<Hero[]>(resolve => setTimeout(resolve, 2000)).then(() => this.getHeroes());
}
getHero(id: number): Promise<Hero> {
return this.getHeroes().then(heroes => heroes.find(hero => hero.id === id));
}
update(hero: Hero): Promise<Hero> {
const url = `${this.heroesUrl}/${hero.id}`;
return this.http.put(url, JSON.stringify(hero), {headers: this.headers})
.toPromise()
.then(() => hero)
.catch(this.handleError);
}
create(heroName: string): Promise<Hero> {
const url = `${this.heroesUrl}`;
return this.getHeroes()
.then(heroes => {
var hero = new Hero(heroes.length, heroName);
return this.http.post(url, JSON.stringify(hero), {headers: this.headers})
.toPromise()
.then(() => hero)
.catch(this.handleError);
});
}
delete(id: number): Promise<void> {
let url = `${this.heroesUrl}/${id}`;
return this.http.delete(url, {headers: this.headers})
.toPromise()
.then(() => null)
.catch(this.handleError);
}
private handleError(error: any) {
console.error('An error ocurred', error);
return Promise.reject(error.message || error);
}
}
ASYNC
Only Promises are available by default
TEMPLATE SYNTAX
<input [value]="firstName">
<div [attr.role]="myAriaRole">
<div [class.extra-sparkle]="isDelightful">
<div [style.width.px]="mySize">
<button (click)="readRainbow($event)">
<div title="Hello {{ponyName}}">
<p>Hello {{ponyName}}</p>
<my-cmp [(title)]="name">
<video #movieplayer ...>
<button (click)="movieplayer.play()">
</video>
<p *myUnless="myExpression">...</p>
<p>Card No.: {{cardNumber | myCardNumberFormatter}}</p>
p>Employer: {{employer?.companyName}}</p>
<svg:rect x="0" y="0" width="100" height="100"/>
<section *ngIf="showSection">
<li *ngFor="let item of list">
<html ng-app>
<!-- Body tag augmented with ngController directive -->
<body ng-controller="MyController">
<input ng-model="foo" value="bar">
<!-- Button tag with ng-click directive, and
string expression 'buttonText'
wrapped in "{{ }}" markup -->
<button ng-click="changeFoo()">{{buttonText | someFilter : orderBy }}</button>
<script src="angular.js">
</body>
</html>
DATA Binding
ng-bind, ng-model, {{}}, events <--> scope, controller
<input [(ngModel)]="userName">
@Input() myProperty;
@Output() myEvent = new EventEmitter();
DATA Binding
Any questions?
Thank for your attention!
Angular 2 in comparison with Angular 1
By diodredd
Angular 2 in comparison with Angular 1
- 337