私の Angular 2 アプリでは、適切なアプリを開始する前に、多数の SVG をロードすることから始めたいと考えています。これを行うには、まずサーバーから svg の場所のリストを読み込み、次にそれぞれを順番にフェッチします。
AppComponent に 'loading' プロパティがあり、ロード中のテキストを表示/非表示にするためにいくつかの ngIf を制御しています。問題は、svg がすべて読み込まれると、Angular が AppComponent のバインディングを更新しないことです。
どうしてこれなの?ゾーンがこれを処理すると思いましたか?
SvgLoader
import {Injectable, Output, EventEmitter, NgZone} from 'angular2/core';
import {Http, Response} from 'angular2/http';
import 'rxjs/Rx';
import {Observable} from 'rxjs/Observable';
const SVG_LIST:string = 'svg/list.json';
@Injectable()
export class SvgLoader {
@Output() state: EventEmitter<string> = new EventEmitter();
private svgs:{[file:string]:string};
constructor(private http:Http){
this.svgs = {};
}
getSvg(path:string):string {
return this.svgs[path];
}
load():void {
this.http.get(SVG_LIST)
.map(res => {
return <Array<string>> res.json().files;
})
.flatMap((files) => Observable.forkJoin(files.map(file => {
return this.http.get('svg/' + file);
})))
.catch(this.handleError)
.mergeAll()
.subscribe(
res => {
let index = res.url.indexOf('svg');
let path = res.url.substring(index);
this.svgs[path] = res.text();
},
error => console.error(error),
() => {
this.state.emit('loaded');
}
);
}
private handleError(error:Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
AppComponent
export class AppComponent {
// On start, list the game sessions
private state:string;
public loading:boolean;
constructor(private svgLoader:SvgLoader){
this.loading = true;
this.state = 'joining';
}
ngOnInit():void {
this.svgLoader.state.subscribe(this.loaded);
this.svgLoader.load();
}
loaded():void {
console.log('loaded');
this.loading = false;
}
}
テンプレート
<div>
<h1 *ngIf="loading">Loading...</h1>
<div *ngIf="!loading">
Loaded
</div>
</div>