Professional Documents
Culture Documents
Warsztaty Angular4
Radosław Kintzi
Łukasz Wojciechowski
Część I - Wprowadzenie
O aplikacji
● Prosty grupowy czat
● Framework Angular4
● TypeScript
O aplikacji
● Prosty grupowy czat
● Framework Angular4
● TypeScript
● UI bazujące na IRC
O aplikacji
● Prosty grupowy czat
● Framework Angular4
● TypeScript
● UI bazujące na IRC
● Protokół oparty o WebSocket (3 ramki)
Build system
● Bazujemy na QuickStart seed z quick start guide
(https://angular.io/docs/ts/latest/quickstart.html)
● Przenieśliśmy pliki wynikowe (.js) do katalogu dist
● Wyłączyliśmy ghost mode w lite-server
Zmiany w build systemie
@Component({
selector: 'app',
template: `<div>{{ name }}</div>`,
styles: [`div { color: red; }`]
})
constructor() {
this.name = "John";
}
}
Komponent - Rejestracja
import { NgModule } from '@angular/core';
import { AppComponent } from
'./app.component';
import { Chat } from './chat.component';
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
],
})
export class AppModule { }
Komponent - Składnia szablonów
DOM (Template)
COMPONENT
[property]=”value”
(event)=”handler”
[(ng-model)]=”property”
Komponent - Data binding
Parent Template
Parent Component
Child Component
Property Binding
{ } { }
Event Binding
Shadow DOM
● Pozwala na separację drzewa DOM i CSS
● W połączeniu z komponentami adresuje style z komponentu tylko do niego
samego.
● Angular dostarcza dodatkowe selektory:
○ :host
○ :host-context
○ /deep/
Komponent - Struktura do implementacji
HeaderComponent
AppComponent
ChatComponent
CreateMessageComponent
Dependency Injection
● Rozluźnianie zależności między elementami systemu.
● Łatwiejsze testowanie
@Component({
...
})
@Injectable()
export class ChatService {
sendNickMessage(msg: NickMessage) {
...
}
sendChatMessage(msg: ChatMessage) {
...
}
}
Część III - Komunikacja z serwerem
Protokół
● Oparty o WebSocket, ramki w formacie JSON
● Protokół obsługuje trzy ramki:
○ ChatMessage - do przesyłania komunikatów tekstowych do/od wszystkich użytkowników
○ NickMessage - do przypisywania i zmiany nicków użytkowników
○ ErrorMessage - do sygnalizowania błędów przez serwer
● Dwie pierwsze ramki wysyła klient do serwera a serwer rozgłasza je do
wszystkich podłączonych użytkowników (również do nadawcy)
● Trzecia ramka wysyłana jest przez serwer tylko do klienta którego dotyczy
sygnalizowany błąd
Protokół - ramka ChatMessage
● Format ramki
{
"type": "ChatMessage",
"data": {
"author": "rakin",
"body": "what’s up"
}
}
console.log(result)
RxJS - Przykład (2)
var list = ['1','1','foo','3','4','5','bar','8','13']; var list = ['1','1','foo','3','4','5','bar','8','13'];
var stream = Rx.Observable.interval(400).take(9)
.map(i=>list[i]);
console.log(result) result.subscribe(x=>console.log(x));
RxJS - Observable, Observer, Subject (1)
var list = ['1','1','foo','3','4','5','bar','8','13'];
var stream = Rx.Observable.interval(400).take(9)
.map(i=>list[i]);
result.subscribe(x=>console.log(x));
RxJS - Observable, Observer, Subject (2)
var list = ['1','1','foo','3','4','5','bar','8','13']; interface Observer<T> {
var stream = Rx.Observable.interval(400).take(9) closed?: boolean;
.map(i=>list[i]);
next: (value: T) => void;
var result = stream error: (err: any) => void;
.map(n=>parseInt(n, 10)) complete: () => void;
.filter(n=>!isNaN(n)) }
.reduce((acc,n)=>acc+n);
result.subscribe(x=>console.log(x));
RxJS - Observable, Observer, Subject (3)
var interval400 = Observable.create((observer)=>{ interface Observer<T> {
var n = 0; closed?: boolean;
var intr = setInterval(() => {
next: (value: T) => void;
observer.next(n);
n++; error: (err: any) => void;
}, 400); complete: () => void;
return ()=>clearInterval(intr); }
});
var list = ['1','1','foo','3','4','5','bar','8','13'];
var stream = interval400.take(9).map(i=>list[i]);
result.subscribe(x=>console.log(x));
RxJS - Observable, Observer, Subject (4)
var obsr = { ... };
var subject = new Subject();
subject.subscribe(obsr);
subject.next(1);
subject.next(2);
...
RxJS - Observable, Observer, Subject (5)
var obsr = { ... };
var subject = new Subject();
subject.subscribe(obsr);
subject.next(1);
subject.next(2);
...
subject.complete();
RxJS - Observable, Observer, Subject (7)
● Observable - utility do tworzenia strumieni danych
○ constructor vs operator (interval() vs take())
result.subscribe(x=>console.log(x));
RxJS - Cold Streams vs Hot Streams (3)
var interval400 = Observable.create((observer)=>{ function makeHot(cold) {
var n = 0; var subject = new Subject();
var intr = setInterval(() => { var refs = 0;
observer.next(n); return Observable.create((observer)=>{
n++; var coldSub;
}, 400); if (refs == 0) {
return ()=>clearInterval(intr); coldSub = cold.subscribe(o=>subject.next(o));
}); }
var list = ['1','1','foo','3','4','5','bar','8','13']; refs++;
var stream = interval400.take(9).map(i=>list[i]); var hotSub = subject.subscribe(observer);
return () => {
var result = stream refs--;
.map(n=>parseInt(n, 10)) if (refs == 0) coldSub.unsubscribe();
.filter(n=>!isNaN(n)) hotSub.unsubscribe();
.reduce((acc,n)=>acc+n); };
});
result.subscribe(x=>console.log(x)); }
var stream = makeHot(interval400);
RxJS w Mildchat client
W Mildchat client użyjemy biblioteki RxJS do komunikacji z serwerem:
TestBed.configureTestingModule({
declarations: [ Chat ],
providers: [
{ provide: ChatService, useValue: chatServiceStub },
],
});
fixture = TestBed.createComponent(Chat);