Angular Training

Rafał Brzoska

Slajdy

Rafał Brzoska

  • Senior Software Developer @ Future Processing
  • Angular Trainer @ FutureProcessing & Bottega IT Minds
  • Speaker
  • Angular, JS, TS

Agenda

  • Wprowadzenie
  • TypeScript
  • Angular CLI
  • Komponenty
  • Szablony
  • Dyrektywy
  • Pipes
  • Serwisy
  • RxJS
  • Http
  • Routing
  • Formularze
  • Imię i nazwisko
  • W FP jestem ...
  • Frontend czy Backend
  • Mam doświadczenie w …
  • Oczekuję od szkolenia i trenera...

 

Co nowego w Angularze

  • Angular 1.x => AngularJS
  • Angular 2+ => Angular
  • Semantic Versioning
  • TypeScript
  • RxJS
  • Change Detection (Zone.js)
  • Komponenty
  • Ogromny ekosystem modułów utrzymywany przez Google
  • Angular CLI
  • Wsparcie dla PWA, SSR, Mobile (NativeScript)

Typescript

  • Typowanie
  • Inferencja typów
  • ES6...ESNext
  • Rozszerzone Klasy
  • Dekoratory
  • Wsparcie IDE

Typy zaawansowane

  • interfejsy
  • kombinacje typów
  • typy generyczne
  • inferencja
  • duck typing
  • type guards

TypeScript

npm install -g typescript


tsc --init

TypeScript

  • string
  • boolean
  • number
  • array
  • enum
  • tuple
  • any
  • void
  • null i undefined
  • never

Interface

interface MyCustomType {
    name: string;
}

interface TestType {
    testNum: number;
    testType: MyCustomType;
}

interface ClassInterface {
    myFn(): void;
    mySecondFunction(num: number): string;
}

Class

class Greeter {
    greeting: string;
    
    constructor(message: string, private userId: number) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

let greeter = new Greeter("world", 1);

Type

type C = { a: string, b?: number }

type stringOrNumber = string | number // Union Type

Generics

function myGenericFunction<T>(arg: T): T {
    return arg;
}

class CustomList<T> {
    private list: T[];

    push(element: T) { list.push(element) };

    getELements(): T[] {
        return this.list;
    }
}

Angular CLI

  • Schematics
  • Aplikacje
  • Biblioteki
  • Preprocesory CSS
  • AOT
  • Inteligentne generowanie kodu
  • Rozszerzenia!!!
  • ...

Angular CLI

  • ng new
  • ng generate
  • ng serve
  • ng build
  • ng test
  • ng update

ng generate

  • component (c)
  • directive (d)
  • service (s)
  • module (m)
  • guard (g)
  • pipe, class, interface ...
    --[option]

 

http://angular.io/cli

External Libs

 

• JS/TS (np. Lodash)

npm install lodash –save
npm install @types/lodash –save-dev

 

• CSS/SASS/LESS(Bootstrap, FontAwesome etc)

Budowa Aplikacji

  • NgModule vs TS/JS Module
  • Drzewo komponentów
  • Root Component
  • Smart Component (Kontener)
  • Dumb Component

Budowa Aplikacji

NgModule

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent
  ],
  imports: [
    BrowserModule,
    RouterModule.forRoot(routes),
  providers: [MyService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Drzewo Komponentów

Root

S

D

D

Komponent

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

@Component

...

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss'],
  // template: '<div></div>',
  // styles: [`.btn { color: red }`],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  providers: [DataService]
})
...

Lifecycle Hooks

Szablony

<p> {{ title }} </p>
<my-component [myInput]="inputData"></my-component>
<my-component (myOutput)="outputHandler($event)"></my-component>
<h1 #myTemplateReference></h1>

Interpolacja

Input - property binding

Output - event binding

template reference variable

Input/Output

@Component({
  selector: 'child-component',
  template: `
    <h3>{{user.name}} says:</h3>
    <p>I, {{user.name}}, am at your service, {{masterName}}.</p>
    <button (click)="handleClick()">Say Hello</button>
  `
})
export class ChildComponent {
  @Input() user: User;
  @Input('master') masterName: string;
  @Output() sayHello = new EventEmitter<string>();

  handleClick() {
     this.sayHello.emit(this.user.name)
  }
}

ChildComponent

Input/Output

@Component({
  selector: 'ParentComponent',
  template: `
    <child-component
      [user]="user"
      [master]="master"
      (sayHello)="handleSayHello($event)">
    </child-component>
  `
})
export class ParentComponent {
  user = { name: 'Alojzy' };
  master = 'Majster';
  handleSayHello(name: string) { alert(name) }
}

ParentComponent

Dyrektywy

  • ngIf
  • ngFor
  • ngClass
  • ngSwitch

ngIf

<div *ngIf="show; else elseBlock">Pokaz to jesli show = true</div>

<ng-template #elseBlock>Pokaż jesli show = false</ng-template>

<div *ngIf="warunek">...</div>

<ng-template [ngIf]="warunek"><div>...</div></ng-template>

*ngIf

[ngIf]

* przy dyrektywie dodaje <ng-template> i upraszcza notacje

ngFor

<ul>
  <li *ngFor="let user of users">{{user.name}}</li>
</ul>
<ng-template ngFor let-user 
             [ngForOf]="users" 
             [ngForTrackBy]="trackById">
  <div {{user.name}}</div>
</ng-template>

* przy dyrektywie dodaje <ng-template> i upraszcza notacje

ngClass

<element [ngClass]="'className1 className2'">...</element>

<element [ngClass]="['className1', 'className2']">...</element>

<element 
  [ngClass]="{'className1 ': true, 'className2 ': true, 'className3 ': false}">
  ...
</element>


<div [class.isOnline]="isOnline">Status</div>

<div [style.color]="isOnline ? 'red' : 'green'">Status</div>

Attribute binding

ngSwitch

<ng-container [ngSwitch]="myNumber">
  <element *ngSwitchCase="1"> jeden </element>
  <element *ngSwitchCase="2"> dwa </element>

  <element *ngSwitchDefault>jakiś numer</element>
</ng-container>

Pipe

  • AsyncPipe
  • DatePipe
  • JsonPipe
  • LowerCasePipe, UpperCasePipe, TitleCasePipe, SlicePipe
  • CurrencyPipe, DecimalPipe, PercentPipe
  • ...
<pre> {{ myObject | json }} </pre>

<p> {{ jakasData | date | uppercase }} </p>

<p> {{ myNumber | currency:'USD' }} </p>

Routing

  • Root Routes, Child Routes
  • Route (path, component, redirect, data)
  • <router-outlet>
  • Router Links
  • Router Services (ActivatedRoute,Router)
  • Guards (CanActivate, CanDeactivate, CanLoad, Resolve…)
  • Lazy Loading (loadChildren: lazy loaded module)

Routing

const routes: Routes = [
  { path: 'home', component: HomeComponent }
];

...
imports: [ RouterModule.forRoot(routes) ],

<nav>
  <a routerLink="/">Home</a>
  <a routerLink="/kontakt">Kontakt</a>
  <a [routerLink]="['/about']">About</a>
</nav>


<router-outlet></router-outlet>

AppModule

AppComponent/NavigationComponent

Serwisy

  • Dekorator @Injectable
  • Domyślnie jako Singleton
  • Globalny dla całej aplikacji (providedIn: 'root')
  • Konieczny wpis do 'providers' w NgModule
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

Serwisy

class MyComponent {
  users: User[];

  constructor(private userService: UserService) { }

  someFunction() { this.users = this.userService.getUsers() }
}

RxJS

  • Observable, Observer, Subject
  • Obsługuje Strumień danych
  • Cancel, Retry
  • fromEvent, fromPromise, toPromise
  • Reactive Forms
  • Angular HTTP Client
  • Cold vs Hot Observable
  • Ponad 100 operatorów

HttpClient

// import in AppModule
import: [... HttpClientModule]
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class MyDataService {
  constructor(private http: HttpClient) { }

  getMyData() {
    this.http.get('http://url...')
  }
}

AppModule

Data Service

Formularze

  • Template Driven Forms
  • Reactive Forms
Made with Slides.com