
__proto__ &
prototype

@tkssharma
github.com/tkssharma
Moving From angular 5 ---- to --- 6
Update your node version to 8 or 8.9.0 or above and Install Angular cli latest globally by npm i -g @angular/cli@latest
Angular 6 uses angular.json as configuration file instead of .anguar-cli.json
Update package.json
"@angular-devkit/core": "^0.6.8",
"@angular/animations": "6.0.7",
"@angular/common": "6.0.7",
"@angular/compiler": "6.0.7",
"@angular/core": "6.0.7",
"@angular/forms": "6.0.7",
"@angular/platform-browser": "6.0.7",
"@angular/platform-browser-dynamic": "6.0.7",
"@angular/router": "6.0.7",
"core-js": "^2.4.1",
"marked": "^0.3.9",
"rxjs": "^6.2.1",
"zone.js": "^0.8.26",
"rxjs-compat": "^6.0.0-rc.0"
Demo angular.json
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"ang2-conduit": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": [
"src/assets",
"src/favicon.ico"
],
"styles": [
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "ang2-conduit:build"
},
"configurations": {
"production": {
"browserTarget": "ang2-conduit:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "ang2-conduit:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"karmaConfig": "./karma.conf.js",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"scripts": [],
"styles": [
"src/styles.css"
],
"assets": [
"src/assets",
"src/favicon.ico"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"ang2-conduit-e2e": {
"root": "e2e",
"sourceRoot": "e2e",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "ang2-conduit:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "ang2-conduit",
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"styleext": "css"
},
"@schematics/angular:directive": {
"prefix": "app"
}
}
}
RxJS upgrade and resolving conflicts
Do npm i -g rxjs-tslint and add below lint configuration in tslint.json
{
"rulesDirectory": [
"node_modules/rxjs-tslint"
],
"rules": {
"rxjs-collapse-imports": true,
"rxjs-pipeable-operators-only": true,
"rxjs-no-static-observable-methods": true,
"rxjs-proper-imports": true
}
}
Operators Name change:
do -> tap
catch -> catchError
switch -> switchAll
finally -> finalize
All operators moved to ‘rxjs/operators'
import { map, filter, reduce } from 'rxjs/operators';
Observable creation methods are moved to ‘rxjs’
import { Observable, Subject, of, from } from 'rxjs';
Welcome to Angular 6.0

Finite Obserables ...
export class TestComponent {
constructor(private http: Http) { }
ngOnInit() {
Observable.timer(1000).subscribe(console.log);
this.http.get('http://api.com').subscribe(console.log);
}
}
This is How you can use it ...
<div *ifRole="'admin'">
Only for Admin
</div>
<div *ifRole="'client'">
Only for Client
</div>
<div *ifRole="'editor'">
Only for Editor
</div>
ViewChildren vs ContentChildren —
ContentChildren includes only elements that exists within the ng-content tag.
ViewChildren don’t include elements that exist within the ng-content tag.
ViewChildren vs ContentChildren —

ContentChildren — All child tab Instance
@Component({
selector: 'tab',
template: `
<p>{{title}}</p>
`,
})
export class TabComponent {
@Input() title;
}
@Component({
selector: 'tabs',
template: `
<ng-content></ng-content>
`,
})
export class TabsComponent {
@ContentChildren(TabComponent) tabs: QueryList<TabComponent>
ngAfterContentInit() {
this.tabs.forEach(tabInstance => console.log(tabInstance))
}
}
@Component({
selector: 'my-app',
template: `
<tabs>
<tab title="One"></tab>
<tab title="Two"></tab>
</tabs>
`,
})
export class App {}
ViewChildren decorator will return the component instance, but you can ask for other tokens:
If you want your component to notify his parent about something you can use the Output decorator with EventEmitter to create a custom event.

@Component({
selector: 'add-todo',
template: `
<input type="text" placeholder="Add todo.." [formControl]="control">
<button (click)="add.next(control.value)">Add</button>
`,
})
export class AddTodoComponent {
control : FormControl = new FormControl("");
@Output() add = new EventEmitter();
}
<add-todo (add)="addTodo($event)"></add-todo>
What is EventEmitter .. a subject ??
export declare class EventEmitter<T> extends Subject<T> {
__isAsync: boolean;
constructor(isAsync?: boolean);
emit(value?: T): void;
subscribe(generatorOrNext?: any, error?: any, complete?: any): any;
}
💪 You have the power of Rx 💪
@Output() add = new EventEmitter().filter(v => !!v);
@Output() add = new BehaviorSubject("Awesome").filter(v => !!v);
EventEmitters are not DOM events
they can't bubble to top of DOM
Event emitter !== DOM

You can't emit event from todo to todoPage component
Solution is
Keep passing the event up the tree
export class TodoComponent {
@Output() toggle = new EventEmitter<any>();
}
export class TodosComponent {
@Output() toggle = new EventEmitter<any>();
}
export class TodosPageComponent {
toggle($event) {}
}
Too much nesting here
Lets do it in native way !
@Component({
selector: 'app-todo',
template: `
<p (click)="toggleTodo(todo)">
{{todo.title}}
</p>
`
})
export class TodoComponent {
@Input() todo;
constructor(private el: ElementRef) {}
toggleTodo(todo) {
this.el.nativeElement
.dispatchEvent(new CustomEvent('toggle-todo', {
detail: todo,
bubbles: true
}));
}
}
Native DOM not a good choice
Lets do using service
@Injectable()
export class TodosService {
private _toggle = new Subject();
toggle$ = this._toggle.asObservable();
toggle(todo) {
this._toggle.next(todo);
}
}
export class TodoComponent {
constructor(private todosService: TodosService) {}
toggle(todo) {
this.todosService.toggle(todo);
}
}
export class TodosPageComponent {
constructor(private todosService: TodosService) {
todosService.toggle$.subscribe(..);
}
}
View Encapsulation
import {Component, ViewEncapsulation}
from 'angular2/angular2';
@component({
selector: 'app',
template: `<p class="green">`,
style: [`
.green { color: green}
`],
encapsulation: 'ViewEncapsulation.Native'
// .Emulated .None
})
export class App {
constructor() {}
}
-
ViewEncapsulation.Emulated
- angular2 view encapsulation enabled // default
-
ViewEncapsulation.None
- No view encapsulation
-
ViewEncapsulation.Native
- view encapsulation using shadow dom
Directives
import {Directive, ElementRef} from 'angular2/angular2';
@Directive({
selector: '[bold]'
})
export class BoldDirective {
constructor(el: ElementRef) {
el.nativeElement.style.fontWeight = 'bold';
}
}
<div class="myapp">
<p bold> Hello world </p>
</div>
Dependency Injection
class Vehicle {
constructor() {
var engine = new Engine();
engine.build();
}
}
Constructor injection
class Vehicle {
constructor(engine: Engine) {
engine.build();
}
}
class Engine {
constructor(nutsNBolts: NutsNBolts) {
nutsNBolts.fit();
}
}
class NutsNBolts {
constructor() {
.....
}
fit() {
}
}
new Vehicle(new Engine(new NutsNBolts()));
// Parent component
import {Component} from 'angular2/angular2';
import {Bootstrap} from 'angular2/angular2';
import {UserService} from './userservice.js';
@Component({ template: `<div> My App </div>` ... })
export class App {
constructor() {
}
}
Bootstrap(App,[UserService]); //UserService available in entire app.
//Child component
import {Component} from 'angular2/angular2';
import {UserService} from './userservice.js';
...
@Component({ ... })
export class SomeComponent {
constructor(user: UserService) { //Singleton
user.dosomething();
}
}
Global Injection
By default all objects injected are singleton
// parent.ts -- parent component
import {RoutineService} from './componentservice';
import {Child} from './child';
@Component({
......
template: `<div>Parent component <child></child> </div>`,
directives: [Child]
providers: [RoutineService]
// viewProviders: [RoutineService]
})
export class App {
constructor(routineservice: RoutineService) {
routineservice.addRoutine(["eat", "sleep", "code"]);
}
}
//child.ts -- child component
import {RoutineService} from './routineservice.js';
@Component({
selector: 'child',
template `<p> I am child component </p>`
})
export class SomeComponent {
constructor(routineservice: RoutineService) { //Singleton
routineservice.deleteRoutine(["sleep"]);
}
}
Component level injection
PIPES
<!-- Date PIPE --!>
<p>{{date | date:'mediumDate'}}</p>
<!-- Sep 1, 2015 --!>
<p>{{date | date:'yMMMMd'}}</p>
<!-- September 1, 2015 --!>
<p>{{date | date:'shortTime'}}</p>
<!-- 3:50 pm --!>
<!-- CURRENCY PIPE --!>
<p>{{43 | currency: 'USD' : true}}</p>
<!-- $43 --!>
<p>{{43 | currency: 'USD' : true : '2.2'}} </p>
<!--$43.00 --!>
<p>{{43 | currency: 'USD' : true : '3.3'}} </p>
<!--$043.000 --!>
Angular2 inbuilt pipes
- currency
- date
- uppercase
- json
- limitTo
- lowercase
- orderBy
- filter
- async
- decimal
- percent
- number
Async Pipes
@Component({
template:
`
<div>
<h1>My Component </h1>
This component is ... {{lazydata | async}}
</div>
`
});
export class App{
lazyData: Promise<string> = null;
constructor() {
this.lazyData = new Promise<string>((resolve: any, reject: any) => {
setTimeout(()=> resolve("lazy"), 3000);
})
}
}
Async pipe also works with Observables.
Async calls

- Http calls return observables.
- Observable is of a love child of Promise and collection/set
- Observable is alias to RxJs Observable
- Rxjs is reactive programming libraray
import {Http} from 'angular2/angular2';
import {Earthquake} from '../models/earthquake';
class EarthquakeService() {
.
.
.
getEarthquakeData(callback:(data: any[]) => void) {
this.http.get('http://earthquake-report.com/feeds/recent-eq?json')
.map((response: any) => {
return response.json();
})
.map((jsonData: any[]) => {
jsonData.forEach((item) => {
this.earthquakeData.push(new Earthquake(item));
});
return this.earthquakeData;
})
.subscribe(
(data:any) => callback(this.earthquakeData), //OnNext
(err:any) => console.log(err), //OnError
() => console.log("call completed") //OnComplete
);
}
}
}
References
- http://blog.thoughtram.io
- http://angularconnect.com/sessions
- https://angular.io
- https://disqus.com/home/forum/victorsavkinsblog
- https://github.com/abhishek-agashe/angular2-playground
?
Angular 6 Advance webinars 00
By Tarun Sharma
Angular 6 Advance webinars 00
- 642