2016-12-08 6 views
4

私は角度2アプリをロードする前にデータベースからいくつかの設定オプションを取得しようとしています。これらの設定オプションに基づいて特定のコンポーネントへのアクセスを制限する必要があるため、角度アプリは起動前にデータが読み込まれるまで待つ必要があります。角度2アプリがAoTを使用して開始する前にデータベースから設定をロード

バックエンドからデータを取得するためにConfigurationServiceを作成しました。ルートモジュールでapp_initializerを使用して、アプリケーションを起動する前にコンフィギュレーションサービスを呼び出しようとしています。私は数ヶ月前に作成した角型アプリ(角型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 

私は「は、これはIBMアカデミーコンパイラとは何かを持っていると思いますを使用しています。ラムダ式を工場で置き換えました。

app.module.ts - 第二には、これは実際にconfigurationserviceを使用してバックエンドからデータを取得

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;     
      } 
     );  
} 

を試してみたが、アプリを起動する前に解決するという約束を待つことはありません。これは、ユーザーがホームページ(誰でもアクセスできる)から起動し、管理者以外のユーザーに制限されているコンポーネントに移動するときに機能します。しかし、ユーザーが制限されているページをリフレッシュすると、設定がロードされる前に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"); 
     } 
    } 
} 

私はすべてのこの時間でアイデアを、私は解決策を探しただけで管理しています私のために働いていないラムダオプションを推薦する人々を見つけるために。 app.module.ts内部からサービスを呼び出すことに遅れていたと私は代わりにmain.tsファイル内からサービスを呼び出す必要があることを指摘しangular gitter channel、上@DzmitryShylovichの助けを借りて

答えて

3

、私は私の問題を解決することができました。彼は私に、folowing plnkrを提供しました。

これは私が自分の解決策でそれを働かせるために行ったことです。

定数。TS

import { OpaqueToken } from '@angular/core' 

export const CONFIG_TOKEN = new OpaqueToken('config'); 

私は、データを解析し、私の構成データを取得するためにWebサービスを呼び出すOpaqueToken to avoid naming collisions

main.ts私main.tsファイルで

import { platformBrowser } from '@angular/platform-browser'; 
import { AppModuleNgFactory } from '../aot/app/app.module.ngfactory'; 
import { CONFIG_TOKEN } from './shared/constants/constants' 

const configApi = "yoururlhere"; 
fetch(configApi, { 
    credentials: 'include' 
}).then(parseResponse); 

function parseResponse(res: any) {  
    return res.json().then(parseData); 
} 

function parseData(data: any) {  
    return platformBrowser([{ provide: CONFIG_TOKEN, useValue: data }]).bootstrapModuleFactory(AppModuleNgFactory); 
} 

を作成しました私のアプリに渡すプロバイダを作成します。私は資格情報を提供するようにフェッチに明示的に指示していないときに401を与えるWebサービス上でWindows認証を使用しているので、含む資格情報を設定します。

app.component.ts私app.componentで

import { Component, OnInit, Inject } from "@angular/core"; 
import { CONFIG_TOKEN } from './shared/constants/constants' 

@Component({ 
    selector: "app", 
    templateUrl: "app.component.html" 
}) 

export class AppComponent implements OnInit { 
    public configuration: any; 
    public isAdmin: boolean; 
    constructor(@Inject(CONFIG_TOKEN) config: any) {   
     this.configuration = config;  
    } 

    ngOnInit() {  
     this.isAdmin = this.configuration.currentUser_IsAdmin; 
    }  
} 

私はWebサービスからもらった構成オブジェクトを使用するために、私の作成したプロバイダを注入することができます。

error TS2304: Cannot find name 'fetch'. 

私は手動WHATWGフェッチtypescriptですがダウンロードすることにより、これを解決:私はこのソリューションを開発する際、私は次のエラーを得たVisual Studioでtypescriptです問題に遭遇した

活字問題

定義ファイル

npm install --save-dev @types/whatwg-fetch 

@DzmitryShylovich、ご協力いただきありがとうございます!

+0

@ types/whatwg-fetchを取り込む際に、重複した識別子エラーを回避するにはどうすればよいですか? lib.d.tsには入力のフェッチが含まれているようですので、手動で入力すると衝突が発生します。 –

関連する問題