ANGULAR w mniej niż 40 minut DARIUSZ KALBARCZYK NG-POLAND
ANGULAR W MNIEJ NIÅ» 40 MINUT DARIUASZ KALBARCZYK
Kim jestem?
www.helion.pl/autorzy/dariusz-kalbarczyk
3
@ngKalbarczyk
#ngPolandConf
4
@ngKalbarczyk
Angular Warsaw
www.meetup.com/Angular-Warsaw
5
@ngKalbarczyk
Czym jest Angular? PLATFORMA do tworzenia aplikacji SPA JEDEN FRAMEWORK Aplikacje WEBOWE Aplikacje MOBILNE Tworzenie aplikacji za pomocÄ… HTML, CSS oraz TYPESCRIPT
6
@ngKalbarczyk
Single page application
ANGULAR pomaga nam tworzyć aplikacje SPA Interakcja odbywa się bez przeładowania strony Komunikacja z serwerem poprzez REST-ful API
7
@ngKalbarczyk
AngularJS vs Angular
? 8
@ngKalbarczyk
angular.io
9
@ngKalbarczyk
Dlaczego Angular? Jeden framework dla web, mobile i desktop Modułowość
Performans
Niesamowite narzędzia: TypeScript, NativeScript, VSC
Wykorzystywany przez miliony
10
@ngKalbarczyk
Od czego zacząć?
Visual Studio Code Nodejs Angular CLI
11
@ngKalbarczyk
Visual Studio Code
12
@ngKalbarczyk
Snippets
13
@ngKalbarczyk
nodejs.org node -v npm -v
14
@ngKalbarczyk
cli.angular.io
15
@ngKalbarczyk
typescriptlang.org
16
@ngKalbarczyk
nativescript.org
Sebastian Witalec @sebawita
17
@ngKalbarczyk
TypeScript
18
@ngKalbarczyk
Konfiguracja IDE tsconfig.json { "compileOnSave": false, "compilerOptions": { "outDir": "./dist/out-tsc", "sourceMap": true, "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es5", "typeRoots": [ "node_modules/@types" ], "lib": [ "es2017", "dom" ‌
19
@ngKalbarczyk
ZACZYNAMY ZABAWĘ
Interpolation {{ value }}
<li>Name: {{ user.name }}</li> <li>Email: {{ user.email }}</li>
21
@ngKalbarczyk
Property Binding [property]="value" <input type="email" [value]="user.email"> <div [style.background-color]="selectedColor"> <div [class.selected]="isSelected">
22
@ngKalbarczyk
Two-Way Data Binding [(ngModel)]="value"
<p>{{name}}</p> <input type="text" [(ngModel)]="name">
23
@ngKalbarczyk
Event Binding (event)="function"
<button
(click)="getPosts()">Pobierz dane z serwera</button>
click / change / keyup / â&#x20AC;Ś
24
@ngKalbarczyk
FORMULARZE <form #newUserForm="ngForm" (ngSubmit)="onSubmit(newUserForm)">
import { NgForm } from '@angular/forms'; onSubmit(form: NgForm) { if (form.valid) { console.log(form.value); // formularz zostaĹ&#x201A; poprawnie zweryfikowany } }
25
@ngKalbarczyk
WALIDACJA <input type="text" placeholder="Miasto" required maxlength="15" [(ngModel)]="city" name="city"
#pickedCity="ngModel"> <div *ngIf="!pickedCity.valid && pickedCity.touched"> Miasto jest wymagane! </div> <button type="submit" [disabled]="!newUserForm.form.valid"> Wyślij </button> <button type="button" (click)="newUserForm.reset()"> Wyczyść </button>
26
@ngKalbarczyk
ARCHITEKTURA
27
@ngKalbarczyk
MODUŁY import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component';
@NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule ], providers: [],
bootstrap: [AppComponent] })
}
Dekorator
Metadane
Moduł główny
export class AppModule { }
28
@ngKalbarczyk
METADANE
Mówią ANGULAROWI jak przetwarzać klasę
29
@ngKalbarczyk
KOMPONENTY DODANIE KOMPONENTU
REJESTRACJA W MODULE
DODANIE SZABLONU
30
@ngKalbarczyk
KOMPONENTY import { Component } from '@angular/core'; @Component({ Dekorator selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; Metadane }
31
@ngKalbarczyk
SELECTOR import { Component } from '@angular/core'; <app-root></app-root>
@Component({
selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; }
32
@ngKalbarczyk
SZABLON import { Component } from '@angular/core'; Szablon
@Component({ selector: 'app-root',
templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; }
33
@ngKalbarczyk
TABLICA STYLI import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html',
styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; }
34
@ngKalbarczyk
KLASA KOMPONENTU import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] })
export class AppComponent { title = 'WDI App'; Klasa zawierajÄ&#x2026;ca } logikÄ&#x2122;
35
@ngKalbarczyk
LIFECYCLE HOOKS HOOK
ngOnChanges()
ngOnInit()
ngOnDestroy()
CEL I CZAS
Wywoływana przed ngOnInit () i za każdym razem, gdy zmienia się jedna lub więcej właściwości wejściowych związanych z danymi.
Inicjuje dyrektywę / komponent.
Wywoływana raz, po pierwszym ngOnChanges().
Wywoływana zanim Angular zniszczy dyrektywę lub komponent.
36
@ngKalbarczyk
DYREKTYWY WBUDOWANE NgIf
NgClass
NgStyle NgForOf
NgSwitch NgSwitchCase
NgTemplateOutlet
NgSwitchDefault
37
@ngKalbarczyk
NgForOf <li *ngFor="let person of people"> {{ person.name }} </li> class ExampleComponent { people: any[ ] = [ { "name": â&#x20AC;&#x17E;Angelika" }, { "name": "Oskar" },
38
@ngKalbarczyk
NgIf @Component({ selector: 'wdi', template: ` <button (click)="show = !show">{{show ? 'Ukryj' : 'Pokaż'}}</button> <div *ngIf="show">Text do wyświetlenia</div> ` }) class WdiComponent { show: boolean = true; }
39
@ngKalbarczyk
NgStyle [ngStyle]="{'font-style': styleExp}"
[ngStyle]="{'max-width.px': widthExp}"
[ngStyle]="objExp" <div [ngStyle]="{'background-color':'green'}"></<div>
[ngStyle]=„{‚background-color' : person.country === 'PL' ? ‚red' : 'black' }"
40
@ngKalbarczyk
PIPE DeprecatedDatePipe
AsyncPipe
DeprecatedCurrencyPipe
DeprecatedDecimalPipe
JsonPipe
DeprecatedPercentPipe
CurrencyPipe PercentPipe
LowerCasePipe
SlicePipe
TitleCasePipe
DatePipe
UpperCasePipe DecimalPipe
41
@ngKalbarczyk
DatePipe <!--output 'Jun 15, 2018'-->
<p>{{today | date}}</p>
<!--output 'Monday, June 15, 2018'-->
<p>{{today | date:'fullDate'}}</p>
<!--output '9:43 AM'-->
<p>{{today | date:'shortTime'}}</p>
<!--output 'Monday, June 15, 2015 at 9:03:01 AM GMT+01:00' -->
<p>The full date/time is {{today | date:'full'}}</p>
<!--output 'Lundi 15 Juin 2015 à 09:03:01 GMT+01:00'-->
<p>Pełna data po francusku: {{today | date:'full':'':'fr'}}</p>
<!--output '2015-06-15 05:03 PM GMT+9'-->
<p>Spersonalizowana data: {{today | date:'yyyy-MM-dd HH:mm a z':'+0900'}}</p>
42
@ngKalbarczyk
JsonPipe @Component({
selector: 'wdi-json-pipe',
template: `<div>
{{data | json}}
<pre> </pre>
</div>`
})
export class WdiJsonPipeComponent {
data: Object = {name: 'WDI', name: 'ngPoland', nested: {type: 1, numbers: [1,3,]}};
}
43
@ngKalbarczyk
AsyncPipe @Component({
selector: 'wdi-async-observable-pipe',
template: â&#x20AC;&#x161;<div>Czas: {{ time | async }}</div>'
})
export class WdiAsyncObservablePipeComponent {
time = new Observable<string>((observer: Subscriber<string>) => {
setInterval(() => observer.next(new Date().toString()), 1000);
});
}
44
@ngKalbarczyk
NAWIGACJA
import { RouterModule, Routes } from '@angular/router';
45
@ngKalbarczyk
NAWIGACJA const appRoutes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'post/:id', component: PostDetailComponent },
{
path: 'blog',
component: BlogListComponent,
data: { title: 'Blog List' }
},
{ path: '**', component: PageNotFoundComponent }
];
46
@ngKalbarczyk
NAWIGACJA <nav>
<a routerLink="/home" routerLinkActive="class1 class2">Home</a> <a routerLink="/blog" routerLinkActive="class1 class2">Blog</a>
</nav>
<div>….</div>
<router-outlet></router-outlet> <div>….</div>
47
@ngKalbarczyk
KOMUNIKACJA GET 200 OK Klient
Serwer
4xx Error 5xx Error
48
@ngKalbarczyk
KOMUNIKACJA
POST { "name":"WDI" } Klient
Serwer
201 Created
49
@ngKalbarczyk
KOMUNIKACJA
GET / POST/ PUT / PATCH / DELETE
50
@ngKalbarczyk
HTTP - app.module.ts import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
BrowserModule,
// import HttpClientModule after BrowserModule.
HttpClientModule,
],
declarations: [
AppComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule {}
51
@ngKalbarczyk
HTTP - app.component.ts import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
readonly ROOT_URL = 'https://jsonplaceholder.typicode.com/';
posts: any;
constructor(private http: HttpClient) {
}
getPosts() { this.posts = this.http.get(this.ROOT_URL + 'posts'); } }
52
@ngKalbarczyk
HTTP - app.component.ts
<button (click)="getPosts()">Pobierz dane z serwera</button>
<div *ngFor="let post of posts | async">{{post | json}}</div>
53
@ngKalbarczyk
WIDOK
54
@ngKalbarczyk
INTERFEJS export interface Post { id: number; userId: number; title: string; body: string; }
55
@ngKalbarczyk
Observable import { Post } from './post'; import { Observable } from 'rxjs/Observable'; . . posts: Observable<Post[ ]>; constructor(private http: HttpClient) {} getPosts() { this.posts = this.http.get<Post[
]>(this.ROOT_URL + 'posts');
} }
56
@ngKalbarczyk
HttpParams import { HttpClient, HttpParams } from '@angular/common/http'; . . . getPosts() { const params = new HttpParams().set('userId', '1'); this.posts = this.http.get(this.ROOT_URL + 'posts', {params}); }
57
@ngKalbarczyk
WIDOK
58
@ngKalbarczyk
HttpHeaders
const headers = new HttpHeaders().set('Authorization', 'auth-token'); this.posts = this.http.get(this.ROOT_URL + 'posts', { headers });
59
@ngKalbarczyk
WIDOK
60
@ngKalbarczyk
RAZEM getPosts() {
HttpParams().set('userId', '1'); let headers = new HttpHeaders().set('Authorization', 'auth-token'); let params = new
this.posts = this.http.get(this.ROOT_URL + '/posts', { params, headers }) }
61
@ngKalbarczyk
POST createPost() { const data: Post = { id: null, userId: 88, title: 'To jest tytuĹ&#x201A;', body: 'To jest body' }; this.newPost = this.http.post(this.ROOT_URL + 'posts', data); } <button (click)="createPost()">Dodaj wpis</button> {{ newPost | async | json }}
62
@ngKalbarczyk
RxJS import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/retry'; import â&#x20AC;&#x161;rxjs/add/observable/of'; . . . this.newPost = this.http.post(this.ROOT_URL + '-posts', data) .retry(3) .catch(err => { console.log(err); return Observable.of(err); });
63
@ngKalbarczyk
WIDOK
64
@ngKalbarczyk
SERWIS import { Injectable } from '@angular/core';
@Injectable() export class PostsService { â&#x20AC;¦ getPosts(): Observable<any> {...} createPost() {...}
65
@ngKalbarczyk
KOMPONENT import { PostsService } from './posts.service';
constructor(private postsService: PostsService) { }
getPosts() { this.posts = this.postsService.getPosts(); } createPost() { this.newPost = this.postsService.createPost(); }
66
@ngKalbarczyk
Gdzie szukaÄ&#x2021; wiedzy?
ULTIMATE ANGULAR
Angular.Love
ANGULAR Warsaw GDG Warszawa
codewithstyle
67
@ngKalbarczyk
Gdzie szukaÄ&#x2021; inspiracji?
@jsPolandConf
68
@ngKalbarczyk
DZIĘKUJĘ ngKalbarczyk ngKalbarczyk dKalbarczyk darek@ngpoland.pl
69
@ngKalbarczyk
>>>Pytania? Zadawaj je, oceniaj prelekcjÄ&#x2122;, komentuj lub polub poprzez sli.do:
WarszawskieDniInformatyki.pl/slido