Angular 2 introduction

50 %
50 %
Information about Angular 2 introduction

Published on May 31, 2017

Author: ChristofferNoring

Source: slideshare.net

1. ANGULAR ( YES ANGULAR 2 ) 1

2. About me Google Developer Expert Telerik Developer Expert Fullstack developer at Digital McKinsey @chris_noring 2 . 1

3. SPA VS NORMAL HOME PAGE 3 . 1

4. NORMAL PAGE 3 . 2

5. 3 . 3

6. PAGE SUMMARY 3 . 4

7. Good at rendering pages, fast SEO, search engine optimization, is easy Good for ecommerce systems showing different product pages Page flickers on loading a page 3 . 5

8. SPA SINGLE PAGE APPLICATION 3 . 6

9. 3 . 7

10. SPA SUMMARY 3 . 8

11. When you want a client on the web, think timesheet, benefit system, excel etc.. More like a client than a page, it's fast SEO is hard, there are no pages to index, there are solutions though Navigation is done by switching content, NO PAGE FLICKERING Rerender part of the page only, with received JSON 3 . 9

12. PROBLEMS TO SOLVE IN AN APP 4 . 1

13. Problems to solve in an app 4 . 2

14. Collecting/Presenting and validating data from Forms Navigation, your app will have more than one view How to read/write data from an API Styling - selecting a CSS framework 4 . 3

15. TYPESCRIPT 5 . 1

16. It's typed javascript 5 . 2

17. Variables and types 5 . 3

18. ES5 var a = 3; var b = 'a string'; var c = false; 5 . 4

19. Typescript let a:number = 3; // will be a number let b:string = 'a string'; // will be a string let c:boolean = false; // will be a boolean let d; // will be supertype any a = "some string" // not ok c = 4 // not ok 5 . 5

20. Functions 5 . 6

21. ES5 function add(a,b) { return a + b; } add(1,3) // 4 add('some','string') // somestring 5 . 7

22. Typescript function add(a:number,b:number):number { return a + b; } add(1,3) // 4 add('some','string') // compile time error 5 . 8

23. Classes 5 . 9

24. ES5 function Hero(name){ this.name; } Hero.prototype.getName = function(){ return this.name; } 5 . 10

25. Typescript class Hero { private name:string; constructor(name:string) { this.name = name; } } getName(){ return this.name; } var hero = new Hero('Arthur') 5 . 11

26. Or even shorter 5 . 12

27. Typescript Creates the backing fields for you and accessor level. class Hero { constructor( private name:string, private description:string) {} } getName(){ return this.name; } let hero = new Hero('Arthur') 5 . 13

28. Interfaces 5 . 14

29. Typescript Forces class to adhere to protocol interface ICharacter { name:string; getName():string; speak(); } class Player implements ICharacter{ name:string; getName():string{ return 'string'; } speak(){ } } 5 . 15

30. Inheritance 5 . 16

31. ES5 function Character(name){ this.name = name; } function Character.prototype.method = function(){} function Player(name){ Character.call(this,name); // call super class constructor } Player.prototype = Object.create(Character.prototype); // inherits var player = new Player('Arthur') player.method(); 5 . 17

32. Typescript class Character{ constructor(protected name:string) {} method(){} } class Player extends Character{ constructor(name:string){ super( name ); } } let player = new Player('Arthur') player.method(); 5 . 18

33. ANGULAR BUILDING BLOCKS 6 . 1

34. Component Structural Directives Pipes ( filters ) Service Module 6 . 2

35. COMPONENT A PIECE OF FUNCTIONALITY WITH ITS OWN HTML TEMPLATE, STYLING AND BACKING CLASS 6 . 3

36. Has a selector, template ( + a bunch more properties ) and a backing class @Component({ selector : 'hello-world', template : ` <div>{{title}}</div> ` }) class HelloWorldComponent{ title:string; constructor() { this.title = 'hello world'; } } //usage <hello-world> 6 . 4

37. SERVICE WHERE YOUR DATA COMES FROM 6 . 5

38. service.ts @Inject() is what makes it available for components @Inject() class Service { getData():string { return 'some data' } } 6 . 6

39. Service is injected into component constructor import { Service } from './service'; @Component({ selector : 'hello-world', template : ` <div>{{title}}</div> ` }) class HelloWorldComponent{ title:string; constructor( private service:Service) { this.title = this.service.getData(); } } 6 . 7

40. MODULE A MODULE IS A CONTAINER THAT HOLDS EVERYTHING LIKE COMPONENTS, SERVICES ETC. 6 . 8

41. app.module.ts A module decorates a class @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, // general helpers like if, loops etc FormsModule, // dealing with forms HttpModule // dealing with fetching data ], providers: [ Service ], bootstrap: [AppComponent] }) export class AppModule {} 6 . 9

42. import : what modules we depend on providers: what services we want other components to be able to use bootstrap : what component is considered the starting point declarations: what components does this module consist of 6 . 10

43. STRUCTURAL DIRECTIVES 6 . 11

44. *ngFor @Component({ selector : 'product-list', template : ` <div *ngFor="let product of products">{{product.name}}</div> ` }) class ProductListComponent{ products = [{name : 'DVD'}, {name : 'CD'}]; } 6 . 12

45. *ngIf="boolean" Only renders something in the DOM if condition is true <div *ngIf="product">{{ product.title }}</div> <div *ngIf="!product">No product is selected</div> 6 . 13

46. *[ngSwitch] <div [ngSwitch]="color"> <div *ngSwitchCase="'blue'">I'm feeling blue</div> <div *ngSwitchCase="'red'">I'm angry</div> <div *ngSwitchCase="'green'">I'm happy</div> </div> 6 . 14

47. INTRODUCING BINDINGS 6 . 15

48. interpolation expression <div>{{ product.name }}</div> <div>{{ 1+1 }}</div> 6 . 16

49. Property binding [attribute] = propertyInComponent <div [title]="tooltip"> class Component { tooltip:string; } 6 . 17

50. [class.classToApply]="boolean" Sets one class <div [class.setThisClass]="basedOnThisCondition"></div> <!-- possible outcome is --> <div class="setThisClass"></div> <!-- or --> <div class=""></div> 6 . 18

52. [style.property]="boolean" Sets one property <div [style.color]="isRed ? 'red' : 'green'"></div> <!-- possible outcome is --> <div class="setThisClass"></div> <!-- or --> <div class=""></div> 6 . 20

53. (event)=method() <button (click)="save()" ></button> class Component{ save(){ console.log('save'); } } 6 . 21

54. [(ngModel)]="propertyOnComponent" This one is called "banana in a box" <input [(ngModel)]="product.name"> <!-- shorthand for the following --> <input [value]="product.name" (input)="product.name = $event.target.value"> class ProductComponent { product:Product; } 6 . 22

55. Pipes 6 . 23

56. A pipe is a way to format your data or filter a collection of data 6 . 24

57. Formatting a list, ordering <div *ngFor="let product of products | sort"> 6 . 25

58. transform method, takes array as input @Pipe({ name: "sort" }) export class ProductSortPipe { transform(array: Array<Product>, args: string): Array<Product> array.sort((a: Product, b: Product) => { if (a.title.toLowerCase() < b.title.toLowerCase()) { return -1; } else if (a.title.toLowerCase() > b.title.toLowerCase()) { return 1; } else { return 0; } }); return array; } 6 . 26

59. Transform method, takes a value as input @Pipe({ name: "bananas" }) export class BananasPipe{ transform(val, ...args){ return `${val}, is bananas B A N A N A S` } } 6 . 27

60. <div> {{ 'This shit' | bananas }} </div> This shit, is bananas B A N A N A S 6 . 28

61. LET'S BUILD AN APP 7 . 1

62. Can also scaffold components, pipes etc, run tests etc.. npm install -g @angular/cli ng new PROJECT-NAME ng serve 7 . 2

63. show a list of items 7 . 3

64. usage, feed it data @Component({ selector : 'app', template : `<product-list>` }) export class AppComponent { products: Product[]; constructor(){ this.products = [ { name : 'Star Wars Episode IV' } ]; } } <product-list [products]="products" > 7 . 4

65. Defining our list component, @Input() @Component({ selector : 'product-list', template : ` <div *ngFor="let product of products"> {{ product.name }} </div> ` }) export class ProductListComponent { @Input() products: Product[]; // input } 7 . 5

66. create an item and add to list 7 . 6

67. <product-list [products]="products" > <create-item (create)="create($event)"></create-item> @Component({ selector : 'app' }) export class AppComponent{ products: Product[]; selected create(name:string) { this.products = [ ...this.products, Object.assign({}, { name : name }) ]; } } 7 . 7

68. And Create Product Component @Component({ selector : 'create-item', template : ` <div> <input type="text" [(ngModel)]="product" > <button (click)="save()">Save</button> </div>` }) export class CreateProductComponent { product:string; @Output create = new EventEmitter(); save(){ this.create.emit( product ); this.product = ''; } 7 . 8

69. Update product, mark product as done 7 . 9

70. AppComponent, add 'selection' and 'update' cabability @Component({ selector : 'app' }) export class AppComponent{ products: Product[]; update(product:Product) { this.products = [ ...this.products.filter( p => p.id !== product.id ), Object.assign({}, product) } select(product:Product){ this.selectedProduct = product; } } <product-list (select)="select($event)" [products]="products" > <create-item (create)="create($event)"></create-item> <edit-product [product]="selectedProduct" (update)="update($event)" 7 . 10

71. Updating product list, give it selection ability @Component({ selector : 'product-list', template : ` <div *ngFor="let product of products"> {{ product.name }} <button (click)="select.emit(product)"> </div> ` }) export class ProductListComponent { @Input() products: Product[]; // input @Output() select = new EventEmitter<Product>(); } 7 . 11

72. Edit product component @Component({ selector : 'edit-product', template : `<div>{{ product.name }}<button (click)="update.emit }) export class EditProductComponent { @Input() product:Product; @Output() update = new EventEmitter<Product>(); } 7 . 12

73. remove item from list 7 . 13

74. Updating App Component, adding 'remove' @Component({ selector : 'app' }) export class AppComponent{ products: Product[]; remove(product:Product){ this.products = this.products.filter( p => p.id !== product } } <product-list [products]="products" (remove)="remove($event)" ></ 7 . 14

75. Updating Product list @Component({ selector : 'product-list' }) export class ProductListComponent{ @Output() remove = new EventEmitter<Product>(); } 7 . 15

76. SUMMARY SO FAR @Input is used for input data to a component @Output is used for invoking methods tied to the component We should have a dedicated component per action 7 . 16

77. ADDING EXTERNAL DATA SOURCE 8 . 1

78. We usually get our data from an API, back comes JSON 8 . 2

79. There are two choices in Angular, RxJS Observables or Promises 8 . 3

80. Http Service 8 . 4

81. import { Http, Response } from '@angular/http'; @Injectable() export class Service{ baseUrl:string = 'http://swapi.co/api/'; constructor(private http:Http){} private getHeroes():Observable<Hero[]>{ return this.httpService .get(`${this.baseUrl}people/`) .map( res => res.json()) .map( this.mapHeroes ); } private mapHeroes(json):Hero[]{ return json.results 8 . 5

82. We are dealing with Observables, they deal with requests in three steps 8 . 6

83. 1) Fetch data 2) Transform data 3) Subscribe + Handle errors this.httpService .get(`${this.baseUrl}people/`) .map( res => res.json()) .map( this.mapHeroes ) .subscribe(fnData, fnError) 8 . 7

84. The promise way 8 . 8

85. private getHeroes():Observable<Hero[]>{ return this.httpService .get(`${this.baseUrl}people/`) .map( res => res.json()) .map( this.mapHeroes ) .toPromise() .then(fnData, fnError); } 8 . 9

86. Subscription vs async pipe 8 . 10

87. @Component({ template : ` <div *ngFor="let hero of heroes | async"> {{ hero.name }} </div> ` }) export class AppComponent{ heroes$:Observable<Hero[]>; constructor( service:Service){ this.heroes = service.getHeroes() } } 8 . 11

88. Async pipe handles subscribe and unsubscribe 8 . 12

89. Without async pipe 8 . 13

90. OnInit, OnDestroy, we need to setup subscribe/unsubscribe @Component({ template : ` <div *ngFor="let hero of heroes"> {{ hero.name }} </div> ` }) export class AppComponent implements OnInit, OnDestroy{ heroes:Hero[]; subscription; constructor( service:Service){ } ngOnInit(){ this.subscription = service.getHeroes().subscribe( data => 8 . 14

91. No async pipe, you need to handle unsubscribe ( to clean up ), generally more boiler plate 8 . 15

92. ROUTING 9 . 1

93. Your app will most likely consist of multiple views, routing is about defining those views and learn to navigate between them 9 . 2

94. Setting base href="" <base href=""> 9 . 3

95. Defining your routes 9 . 4

96. { path : ComponentToHandlePath } const appRoutes: Routes = [ { path: '', component: HomeComponent }, { path: 'products', component: ProductContainerComponent }, { path: 'products/:id', component: ProductDetailComponent }, // capture the rest { path: '**', component: PageNotFoundComponent } ]; 9 . 5

97. Setup routes 9 . 6

98. RouterModule.forRoot( routes ) @NgModule({ declarations: [ // ...declarations ], imports: [ // ... modules // setup route RouterModule.forRoot(appRoutes) ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } 9 . 7

99. Creating an outlet, where the content should be rendered 9 . 8

100. header here <router-outlet></router-outlet> footer here 9 . 9

101. Routing by links 9 . 10

102. <div> <a routerLink="/" routerLinkActive="active">Home</a> | <a routerLink="/products" routerLinkActive="active">Products </div> 9 . 11

103. Routing programatically 9 . 12

104. import { Router } from '@angular/router'; @Component({}) export class ListComponent{ gotoDetail(){ this.router.navigate(['/products', 1]); } } 9 . 13

105. Accessing route parameters 9 . 14

106. route.params.subscribe( param => do something ) export class ProductDetailComponent { product:Product; constructor( private router:Router, private route:ActivatedRoute, private productService: ProductService ){ this.route.params .switchMap( param => this.productService.getProduct(param. .subscribe( data => this.product = data ) } } 9 . 15

107. Route guards, aka security 9 . 16

108. canActivate = serviceThatHandlesAuthorization { path : 'admin', component: AdminComponent, canActivate : [AuthGuard] } 9 . 17

109. CanActivate true/false export class AuthGuard implements CanActivate { canActivate(){ console.log('Admin Component Can activate'); // talk to an return false; } } 9 . 18

110. FORMS 10 . 1

111. There are two different ways to handle forms, Template Forms and Reactive Forms 10 . 2

112. Template forms 10 . 3

113. Pristine = not touched Invalid = data validation error Dirty = user has entered data 10 . 4

114. ngSubmit, triggered by button or input type="submit" Creating a reference to ngForm means we can see if its valid <form (ngSubmit)="heroForm.valid && submit()" #heroForm="ngForm" <div> <h3>Form</h3> Pristine <strong>{{ heroForm.pristine }}</strong> <br> Invalid <strong>{{ heroForm.invalid }}</strong> <br> Dirty <strong>{{ heroForm.dirty }}</strong> <br> </div> <div><button>Save</button></div> {{ heroForm.valid }} </form> 10 . 5

115. formName.controls.fieldName.errorType, will give the error if set e.g heroForm.controls.name.errors = true <div> <input [(ngModel)]="hero.title" #name ="ngModel" name="name" minlength="2" required > </div> valid {{ name.valid }} <br> pristine {{ name.pristine }} <br> All errors {{ heroForm.controls.name.errors | json }} 10 . 6

116. Further reading & Learning angular.io angular.io/resources Rxjs 5 Ultimate https://ultimateangular.com/ Free book on Angular 2, https://codecra .tv/ London Javascript ( my group 1700 members ) https://www.meetup.com/London-Javascript/ Everything showed today is here : https://github.com/so chris/Angular2-demo 11

117. Thank you 12

#name presentations

Add a comment