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
Szkolenie Angular - Podstawy
By Rafał Brzoska
Szkolenie Angular - Podstawy
- 506