Angular 2
Core concepts
History
- Started by Miško Hevery in 2009
- Challenged to migrate a project from GWT (3 devs × 6 months) to Angular in 2 weeks ....... and FAILED
- version 1.0 released in 2012
- current version is 1.6.1 (23/12/2016)
- $scope, $http, $resource, two-way binding
- Global API - angular.copy(), angular.equals(), -angular.bind() ...
- $broadcast, $emit, $watch, $eval, $digest, $apply...
- Directives (58 build-in)
- Services, Factories, Providers
Angular 2 vs 1.x
TypeScript
https://www.typescriptlang.org/
- Developed and maintained by Microsoft
- Open source programming language
- Optional static typing and class-based OOP
- Anders Hejlsberg, lead architect of C# and creator of Delphi and Turbo Pascal, has worked on the development of TypeScript.
Text
Text
-The TypeScript compiler is implemented in TypeScript
TypeScript = ES6 + Types + Annotations
class Animal {
constructor(public name: string) { }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
let sam = new Snake("Sammy the Python");
sam.move();
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Animal = (function () {
function Animal(name) {
this.name = name;
}
Animal.prototype.move = function (distanceInMeters) {
if (distanceInMeters === void 0) { distanceInMeters = 0; }
console.log(this.name + " moved " + distanceInMeters + "m.");
};
return Animal;
}());
var Snake = (function (_super) {
__extends(Snake, _super);
function Snake(name) {
return _super.call(this, name) || this;
}
Snake.prototype.move = function (distanceInMeters) {
if (distanceInMeters === void 0) { distanceInMeters = 5; }
console.log("Slithering...");
_super.prototype.move.call(this, distanceInMeters);
};
return Snake;
}(Animal));
var sam = new Snake("Sammy the Python");
sam.move();
- Component-Based
- Templates
- Reduced and simplified build-in directives
(*ngIf, *ngFor, [ngSwitch], [ngSwitchCase], ngSwitchDefault, [ngClass])
- One-way data binding (two-way is also available)
- New Dependency Injection system
- Improved Change Detection System
- Native support
Angular 2
- Framework for building client applications in TypeScript and HTML
- Consists of several libraries
(angular/core, angular/platform-browser, angular/http, angular/forms, ...)
- Angular Application =
Modules[(angularized HTML + Directives) + Services]
- Launching the application = Bootstrap the root module
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<div>
<h1>Hello {{name}}</h1>
</div>
`
})
export class AppComponent { name = 'World'; }
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ Logger ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
// main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
// index.html
<body>
<my-app>Starting application...</my-app>
</body>
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ Logger ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
export class HeroListComponent implements OnInit {
heroes: Hero[];
selectedHero: Hero;
constructor(private service: HeroService) { }
ngOnInit() {
this.heroes = this.service.getHeroes();
}
selectHero(hero: Hero) { this.selectedHero = hero; }
}
<h2>Hero List</h2>
<p><i>Pick a hero from the list</i></p>
<ul>
<li *ngFor="let hero of heroes" (click)="selectHero(hero)">
{{hero.name}}
</li>
</ul>
<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>
@Component({
moduleId: module.id,
selector: 'hero-list',
templateUrl: 'hero-list.component.html',
providers: [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}
<li *ngFor="let hero of heroes"></li>
<hero-detail *ngIf="selectedHero"></hero-detail>
Structural
Attributes
// highlight.directive.ts
import { Directive, ElementRef, Input } from '@angular/core';
@Directive({ selector: '[highlight]' })
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
// page.html
<p highlight>Highlight me!</p>
// app/logger.service.ts
@Injectable()
export class Logger {
log(msg: any) {
console.log(msg);
}
error(msg: any) {
console.error(msg);
}
warn(msg: any) {
console.warn(msg);
}
}
// app.module.ts
@NgModule({
imports: [ ... ],
providers: [ Logger ],
exports: [ ... ],
bootstrap: [ ... ]
})
export class AppModule {
}
// app/hero-list.component.ts
@Component({
selector: 'hero-list',
templateUrl: 'hero-list.component.html',
providers: [ HeroService ]
})
export class HeroListComponent {
constructor(private service: HeroService) {
}
}
// hero-list.component.html
<li>{{hero.name}}</li>
<hero-detail [hero]="selectedHero"></hero-detail>
<li (click)="selectHero(hero)"></li>
// hero-detail.component.html
<input [(ngModel)]="hero.name">
// --- understanding ngModel ---
<input [ngModel]="hero.name" (ngModelChange)="hero.name = $event">
Application state change is caused by three things:
Events - User events like click, change, input, submit, …
XMLHttpRequests - E.g. when fetching data from a remote service
Timers - setTimeout(), setInterval(), because JavaScript
ObservableWrapper.subscribe(this.zone.onTurnDone, () => {
this.zone.run(() => {
this.tick();
});
});
tick() {
// perform change detection
this.changeDetectorRefs.forEach((detector) => {
detector.detectChanges();
});
}
Change detection
@Component({
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ImmutableTodoCmp {
...
}
// todos.component.ts
type ObservableTodo = Observable<todo>;
type ObservableTodos = Observable<array>>;
@Component({
selector: 'todos',
template: `<todo *ngFor="let t of todos" todo="t"></todo>`
})
class ObservableTodosCmp {
todos:ObservableTodos;
...
}
// todo.component.ts
@Component({selector:'todo'})
class ObservableTodoCmp {
todo: ObservableTodo;
...
}
Resources
https://angular.io/
http://learnangular2.com/
http://blog.ng-book.com/
https://angular.io/docs/ts/latest/guide/cheatsheet.html
https://dzone.com/articles/typed-front-end-with-angular-2
http://angular2academy.com/2017/01/08/angular-2-core-components/
https://blog.thoughtram.io/angular/2016/02/01/zones-in-angular-2.html
https://vsavkin.com/change-detection-in-angular-2-4f216b855d4c#.tigfnjcvx
https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html
https://egghead.io/courses/angular-2-fundamentals
http://courses.angularclass.com/p/angular-2-fundamentals
Thank you!
Angular 2. Core concepts
By Stanislav Oaserele
Angular 2. Core concepts
- 884