angular 2 アプリをロードする前に、データベースからいくつかの構成オプションを取得しようとしています。これらの構成オプションに基づいて特定のコンポーネントへのアクセスを制限する必要があるため、Angular アプリは開始する前にデータが読み込まれるのを待つ必要があります。
したがって、バックエンドからデータを取得するための ConfigurationService を作成しました。ルート モジュールで app_initializer を使用して、アプリを起動する前に構成サービスを呼び出そうとしています。数か月前に作成したAngularアプリ(Angular RC4)でこれを行うことができ、今回も最初は同じようにしようとしました。
app.module.ts - 最初の試行
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';
import { HttpModule } from '@angular/http';
import { ConfigurationService } from "./shared/services/configuration.service";
@NgModule({
imports: [
...
],
declarations: [
...
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: (config: ConfigurationService) => () => config.loadConfiguration(),
deps: [ConfigurationService]
},
ConfigurationService
],
bootstrap: [AppComponent]
})
export class AppModule { }
これにより、次のエラーが発生しました。
Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function
これは、私が使用している AoT コンパイラと関係があると思います。ラムダ式をファクトリに置き換えました。
app.module.ts - 2 回目の試行
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';
import { HttpModule } from '@angular/http';
import { ConfigurationService } from "./shared/services/configuration.service";
import { ConfigurationServiceFactory } from "./shared/services/configuration.service.factory";
@NgModule({
imports: [
...
],
declarations: [
...
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: ConfigurationServiceFactory,
deps: [ConfigurationService]
},
ConfigurationService
],
bootstrap: [AppComponent]
})
export class AppModule { }
configuration.service.factory.ts
import { ConfigurationService } from "./configuration.service";
export function ConfigurationServiceFactory(configurationService: ConfigurationService) {
return configurationService.loadConfiguration()
.then(currentUser => {
configurationService.currentUser = currentUser;
}
);
}
これは実際には構成サービスを使用してバックエンドからデータを取得しますが、アプリを開始する前に promise が解決されるのを待ちません。これは、ユーザーがホームページ (誰でもアクセスできる) から開始してから、管理者以外のユーザーに制限されているコンポーネントに移動するときに機能します。しかし、ユーザーが制限されているページを更新すると、構成が読み込まれる前に OnInit (ユーザーがアクセスできるかどうかを判断する場所) が起動します。私の場合、これにより、ユーザーはアクセスできるはずのページへのアクセスが拒否されます。
configuration.service.ts
import { Injectable } from "@angular/core";
import { Http, Response } from '@angular/http';
import { CurrentUser } from "../models/currentuser.model";
@Injectable()
export class ConfigurationService {
public apiUrl: string = "api/";
public currentUser: CurrentUser;
constructor(private http:Http) {}
/**
* Get configuration from database
*/
public loadConfiguration(): Promise<CurrentUser> {
return this.http.get(this.apiUrl + "application/GetDataForCurrentUser")
.toPromise()
.then(this.extractData)
.catch(this.handleError);
}
}
コンポーネントの実装
import { Component, OnInit } from '@angular/core';
import { MessageService } from '../shared/message/message.service'
import { ConfigurationService } from "../shared/services/configuration.service";
@Component({
selector: 'simple',
templateUrl: 'simple.component.html'
})
export class SimpleComponent implements OnInit{
constructor(private messageService: MessageService, private configurationService: ConfigurationService) {
}
ngOnInit() {
if (!this.configurationService.isAdmin()) {
this.messageService.addMessage("Access denied", "danger");
}
}
}
現時点ではアイデアがありません。解決策を探しましたが、ラムダオプションを推奨している人々を見つけることができましたが、これは私にとってはうまくいきません。