Ich versuche, einige Konfigurationsoptionen aus der Datenbank zu bekommen, bevor ich meine angular 2 App lade. Die eckige App muss vor dem Start auf das Laden der Daten warten, da der Zugriff auf bestimmte Komponenten basierend auf diesen Konfigurationsoptionen eingeschränkt sein sollte.Laden der Konfiguration aus der Datenbank, bevor Angular 2 App mit AoT startet
Also habe ich einen ConfigurationService erstellt, um die Daten aus dem Backend zu bekommen und ich versuche mit dem app_initializer im root-Modul den Konfigurationsservice vor dem Starten der App aufzurufen. Ich habe es geschafft, dies in einer eckigen App zu tun, die ich vor ein paar Monaten erstellt habe (eckige RC4), und habe versucht, es dieses Mal auf die gleiche Weise zu tun.
app.module.ts - Erster Versuch
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 { }
Dies führte zu dem folgenden Fehler:
Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function
Ich denke, das etwas mit den AOT-Compiler zu tun hat, die ich m verwenden. Ich habe die Lambda-Ausdrücke durch eine Fabrik ersetzt.
app.module.ts - Zweiter Versuch
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;
}
);
}
Dies wird tatsächlich die Daten aus dem Backend des configurationservice verwenden, aber Warten Sie nicht auf das Versprechen zu lösen, bevor Sie die App starten. Es funktioniert, wenn der Benutzer auf der Homepage startet (die für jeden zugänglich ist) und dann zu einer Komponente navigiert, die für Benutzer ohne Administratorrechte gesperrt ist. Wenn der Benutzer jedoch die eingeschränkte Seite aktualisiert, wird das OnInit (wo ich feststellen kann, ob ein Benutzer Zugriff hat) ausgelöst, bevor die Konfiguration geladen werden kann. Dies führt in meinem Fall dazu, dass Benutzern der Zugriff auf Seiten verweigert wird, auf die sie zugreifen dürfen.
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);
}
}
Component Implementierung
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");
}
}
}
Ich bin ganz aus Ideen zu diesem Zeitpunkt habe ich nach einer Lösung gesucht, aber nur geschafft Leute finden, die die Lambda-Option empfehlen, was bei mir nicht funktioniert.
Wie umgehen Sie doppelte Bezeichnerfehler beim Einziehen von @ types/whatwg-fetch? Es scheint, als ob lib.d.ts jetzt Fetch-Typings enthält, so dass es beim manuellen Hinzufügen der Typings zu Kollisionen kommt. –