Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Commit University - Exploring Angular 2

383 views

Published on

Probabilmente il framework javascript più atteso di sempre, evoluzione di uno dei framework più longevi ed usati nello sviluppo front end. Si vedranno alcune delle novità introdotte e delle scelte radicali fatte da Google per la nuova versione di Angular

Published in: Software

Commit University - Exploring Angular 2

  1. 1. Exploring Angular 2
  2. 2. Angular 2 The Next Framework
  3. 3. @cef62 github.com/cef62 Senior frontend engineer @ Staff member of Frontenders Verona Italian React & Angular Communities Maintainer MATTEO RONCHI
  4. 4. AngularJS history • AngularJS was originally developed in 2009 by Misko Hevery and Adam Abrons • Misko Hevery started to work for Google in 2009 • 1st release of AngularJS: 1 developer, 3 weeks, 1000 loc • AngularJS version 1.0 was released in 2012 by Google • Angular version 2 was released in September 2016 after 2 years development
  5. 5. WELCOME TO THE FUTURE
  6. 6. Angular 2 features • Optimized for both desktop and mobile • Ahead of Time (AoT) compilation • Incredible performances • Native Reactive support
  7. 7. ANGULAR 2 BASICS @INJECTABLE
  8. 8. export class MyService { getData() { return this.loadData.load(); } }
  9. 9. import { Injectable } from `angular2/core`; @Injectable() export class MyService { constructor(private loadData:LoadData) {} getData() { return this.loadData.load(); } }
  10. 10. ANGULAR 2 BASICS @COMPONENT
  11. 11. import { Component } from '@angular/core'; @Component({ selector: 'hello', template: '<p>Hello, {{name}}</p>' }) export class Hello { name: string; constructor() { this.name = 'World'; } }
  12. 12. ANGULAR 2 BASICS @DIRECTIVE
  13. 13. import { Directive, HostListener } from '@angular/core'; @Directive({ selector: `[confirm]` }) export class ConfirmDirective { @HostListener(`click`, [`$event`]) confirmFirst(event: Event) { return window.confirm( `Are you sure you want to do this?` ); } } // Usage <button type="button" (click)="visitOtherPage()" confirm>Visit another page</button>
  14. 14. ANGULAR 2 BASICS @PIPES
  15. 15. import { Component } from '@angular/core'; @Component({ selector: `product-price`, template: `<p>Price: {{ price | currency }}</p>` }) export class ProductPrice { price: number = 99.99; }
  16. 16. import { Pipe, PipeTransform } from '@angular/core'; const UNITS = ['B', 'KB', 'MB', 'GB']; @Pipe({ name: 'formatFileSize' }) export class FormatSize implements PipeTransform { transform( bytes: number = 0, precision: number = 2 ) : string { if (!isFinite(bytes)) return ‘?'; let unit = 0; while ( bytes >= 1024 ) { bytes /= 1024; unit ++; } return bytes.toFixed(precision) + ' ' + UNITS[unit]; } }
  17. 17. ANGULAR 2 BASICS HTTP SERVICE
  18. 18. import {Injectable} from '@angular/core'; import {Http, Response} from '@angular/http'; import {Observable} from 'rxjs'; import {Hero} from './hero'; @Injectable() export class LoadDataService { constructor(private http: Http) {} search(term: string): Observable<Hero[]> { return this.http .get(`app/heroes/?name=${term}`) .map((r: Response) => { return r.json().data as Hero[] }); } }
  19. 19. IN THE ZONE
  20. 20. AngularJS $digest cycle • AngularJS engine is built using a dirty checking algorithm. • Application state is a single entity connected to every visual component and calculated every time a component mutates some data • It’s very easy to trigger unwanted $digest cycles impacting performances • Very difficult to debug
  21. 21. Angular 2 Change Detection engine • Based on ngZone • Recalculate the components tree state after every async interaction (events, timers, observables..) • Every component has its own Change Detector • Component’s Change Detector is generated at runtime to improve performances • Developers can control how and when components are recalculated
  22. 22. – ngBook2 “When one of the components change, no matter where in the tree it is, a change detection pass is triggered for the whole tree, from top to bottom.”
  23. 23. CD CD CD CD CDCD CD CD CHANGE DETECTION TRAVELS TOP TO BOTTOM ChangeDetection Flow
  24. 24. CHANGE DETECTION IS DEFINED AT COMPONENT LEVEL
  25. 25. • Every component gets a change detector responsible for checking the bindings defined in its template • ChangeDetectionStrategy • default: update the component every time data changes • onPush: update the component only when its inputs change or the component requests to be updated
  26. 26. CHANGE DETECTION (onPush) WITH IMMUTABLE DATA CD CD CD CD CD CD ChangeDetection Flow
  27. 27. CHANGE DETECTION (onPush) WITH OBSERVABLES CD CD CD CD ChangeDetection Flow
  28. 28. TYPESCRIPT: A FIRST CLASS CITIZEN
  29. 29. Why typescript • Angular2 Dependency Injection system is based on type reflection • Annotations offer a powerful and very expressive way to describe elements
  30. 30. Pros • Improve Developer Experience with better tools • Compile time error check • Type safety • Better documentation • Easy to adopt for backend developers
  31. 31. Cons • Increase project’s technical debt • Slower learning curve for traditional javascript developer • Impossible to remove without a complete rewrite
  32. 32. THINKING COMPONENTS
  33. 33. Modern web is all about components • Thinking of components instead of views improves decoupling and separation of concerns • Components are composable and highly reusable • Easier to test • UX and UI teams integrate better
  34. 34. A component is • exported as a custom HTML tag: <tab-bar /> • defined by an HTML template • enhanced using the @component decorator • controlled using its inputs and outputs • initialized by Angular Dependency Injection engine
  35. 35. SELECTOR @COMPONENT
  36. 36. import { Component } from '@angular/core'; @Component({ selector: 'hello', template: '<p>Hello, {{name}}</p>' }) export class Hello { name: string; constructor() { this.name = 'World'; } }
  37. 37. selector is the element property that we use to tell Angular to create and insert an instance of this component.
  38. 38. COMPONENT TEMPLATE @COMPONENT
  39. 39. template is an HTML string that tells Angular what needs to be to rendered in the DOM. templateUrl is a relative path to a file containing the component HTML string.
  40. 40. TEMPLATE SYNTAX • template tags {{ expression }}: Execute arbitrary expressions. Eg: {{1+1}. • property binding [key]=“value”. Used to pass data to a component. • event binding (event)=“expression”. Expression executed anytime the registered event fires. • 2-way binding <input [(ngModel)]=“u.name"> Requires to import `FormsModule` to be used.
  41. 41. INPUTS @COMPONENT
  42. 42. import {Component, Input} from `@angular/ core`; @Component({ selector: `hello`, template: `<p>Hello, {{name}}</p>` }) export class Hello { @Input() name: string; }
  43. 43. import { Component } from `@angular/core`; @Component({ selector: `hello`, inputs: [`name`], template: `<p>Hello, {{name}}</p>` }) export class Hello {}
  44. 44. // To bind to a raw string <hello name="World"></hello> // To bind to a variable in the parent scope <hello [name]="userName"></hello>
  45. 45. OUTPUTS @COMPONENT
  46. 46. import {Component} from `@angular/core`; @Component({ selector: `counter`, template: ` <div> <p>Count: {{ num }}</p> <button (click)="increment()">Increment</button> </div> ` }) export class Counter { num: number = 0; increment() { this.num++; } }
  47. 47. import { Component, EventEmitter, Output } from `@angular/core`; @Component({ selector: `counter`, template: ` <div> <p>Count: {{ count }}</p> <button (click)="increment()">Increment</button> </div> ` }) export class Counter { count: number = 0; @Output() result: EventEmitter = new EventEmitter(); increment() { this.result.emit(this.count); } }
  48. 48. CHILD COMPONENTS @COMPONENT
  49. 49. import {Component, ViewChild} from `@angular/ core`; import {Alert} from `./alert.component`; @Component({ selector: `app`, template: ` <my-alert>My alert</my-alert> <button (click)="showAlert()">Show Alert</ button>` }) export class App { @ViewChild(Alert) alert: Alert; showAlert() { this.alert.show(); } }
  50. 50. import {Component, ViewChild} from `@angular/core`; import {Alert} from `./alert.component`; @Component({ selector: `app`, template: ` <my-alert>My alert</my-alert> <input #msg type=“text” /> <button (click)="showAlert()">Show Alert</button>` }) export class App { @ViewChild(Alert) alert: Alert; @ViewChild(`msg`) msgInput; showAlert() { const txt = this.msgInput.nativeElement.value; this.alert.show(txt); } }
  51. 51. CONTENT TRANSCLUSION @COMPONENT
  52. 52. import {Component, Input} from `@angular/core`; @Component({ selector: `hello`, template: `<div> <p>Hello, {{name}}</p> <ng-content><p>No extra data</p></ng-content> </div>` }) export class Hello { @Input() name: string; } // Usage <hello name=“Matteo”> <div> <h1>Some other data</h1> <p>Some text</p> </div> </hello>
  53. 53. COMPONENT LIFECYCLE
  54. 54. Components & Directives shared lifecycle ngOnChanges input property value changes ngOnInit Initialization step ngDoCheck every change detection cycle ngOnDestroy before destruction
  55. 55. import { Component, OnInit } from '@angular/core'; @Component({ selector: 'hello', template: '<p>Hello, {{name}}</p>' }) export class Hello implements OnInit { name: string; constructor() { this.name = 'World'; } ngOnInit() { // do something to initialize the component } }
  56. 56. import { Directive, OnInit, OnDestroy } from '@angular/core'; @Directive({ selector: `[mySpy]` }) export class SpyDirective implements OnInit, OnDestroy { constructor(private logger: LoggerService) { } ngOnInit() { this.logIt(`onInit`); } ngOnDestroy() { this.logIt(`onDestroy`); } private logIt(msg: string) { this.logger.log(`Spy ${msg}`); } } // Usage <div mySpy>...</div>
  57. 57. –Angular official docs “Angular only calls a directive/component hook method if it is defined.”
  58. 58. COMPONENT STYLE INLINE STYLES
  59. 59. import { Component } from '@angular/core'; const baseStyle = { backgroundColor: 'green', padding: '10px' }; @Component({ selector: 'hello', template: ‘<p [ngStyle]="style">Hello!</p>' }) export class Hello { style: any = baseStyle; }
  60. 60. COMPONENT STYLE VIEW ENCAPSULATION
  61. 61. • Emulated (default) - styles from main HTML propagate to the component. Styles defined in this component's @Component decorator are scoped to this component only. • Native (shadow DOM)- styles from main HTML do not propagate to the component. Styles defined in this component's @Component decorator are scoped to this component only. • None - styles from the component propagate back to the main HTML and therefore are visible to all components on the page. ——— Be careful with apps that have None and Native components mixed in the application. All components with None encapsulation will have their styles duplicated in all components with Native encapsulation.
  62. 62. import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: ‘hello', styles: [` .main { background-color: green; padding: 10px; } `], encapsulation: ViewEncapsulation.Emulated, template: `<p class="main">Hello!</p>` }) export class Hello {}
  63. 63. // OUTPUT HTML <p class="main" _ngcontent-yok-5="" >Hello!</p> // output css (inside <head>) .main[_ngcontent-yok-5] { background-color: green; padding: 10px; }
  64. 64. BE REACTIVE! OBSERVE ALL THE THINGS!
  65. 65. –Angular official docs “Observables open up a continuous channel of communication in which multiple values of data can be emitted over time […] Angular 2 uses observables extensively - you'll see them in the HTTP service and the event system…”
  66. 66. –A. Staltz “A stream is a sequence of ongoing events ordered in time. It can emit 3 different things: a value, an error, or a "completed" signal. Consider that the "completed" takes place, for instance, when the current window is closed.”
  67. 67. OBSERVABLES vs PROMISES
  68. 68. • Both provide us with abstractions that help us deal with the asynchronous nature of our applications. • Observables are cancellable. • Observables can be retried using one of the retry operators provided by the API, such as retry and retryWhen. • Promises require the caller to have access to the original function that returned the promise in order to have a retry capability.
  69. 69. import { Observable } from ‘rxjs/Observable'; const dataStream = new Observable((observer) => { setTimeout(() => { observer.next(42); }, 1000); setTimeout(() => { observer.next(43); }, 2000); setTimeout(() => { observer.complete(); }, 3000); }); const subscription = dataStream.subscribe( (value) => this.values.push(value), (error) => this.anyErrors = true, () => this.finished = true );
  70. 70. import { Component, OnInit, ViewChild } from `@angular/core`; import { Observable } from 'rxjs'; @Component({ selector: `app`, template: `<input type="text" #username />` }) export class App implements OnInit { @ViewChild(`username`) username: any; ngOnInit(): void { Observable .fromEvent(this.username.nativeElement, 'keyup') .map((e: any) => e.target.value) .filter((text: string) => text.length > 5) .debounceTime(1000) .subscribe((text: string) => this.submit(text)); } submit(text: string): void { console.log('submitted: ', text); } }
  71. 71. Bootstrapping Angular
  72. 72. Bootstrapping is an essential process in Angular - it is where the application is loaded when Angular comes to life. Bootstrapping Angular 2 applications is certainly different from Angular 1.x, but is still a straightforward procedure.
  73. 73. // app.modules.ts import { BrowserModule } from '@angular/platform- browser'; import { NgModule } from '@angular/core'; import { HttpModule } from '@angular/http'; import { AppComponent } from './[PATH]/app.component'; import { MyComponent } from ‘./[PATH]/some.component'; import { SomeService } from “./[PATH]/some.service"; @NgModule({ declarations: [AppComponent, MyComponent], providers: [SomeService], imports: [BrowserModule, HttpModule], bootstrap: [AppComponent] }) class AppModule {}
  74. 74. // main.ts import { platformBrowserDynamic } from '@angular/ platform-browser-dynamic'; import { AppModule } from './app/'; // Bootstrap main component platformBrowserDynamic().bootstrapModule(AppModule);
  75. 75. angular-cli FAST PROJECT SETUP WORKING EXAMPLE: github.com/commit-university/exploring-angular-2
  76. 76. THANKS! @CEF62

×