问题
I try to set the APP_BASE_HREF in the "CoreModule" with a value from a async rest call. I can't see how this is done, because the provide method needs to return a string.
for example:
@NgModule({
imports: [
...
HttpModule
],
...
providers: [
...
...
BackendRequestClass,
{ provide: APP_BASE_HREF, useFactory: () => () => return '/some/path', deps: [], multi: true }
],
});
but when I need the value from a webservice, I can't return the string. Any ideas how this could be done?
thx
回答1:
I tried your solution. The problem is, that at the time
{ provide: APP_BASE_HREF, useFactory: (config) => config.appBaseHref, deps: [ConfigService] }
the config.appBaseHref is not set yet.
When I debug the code I see, that the APP_INITIALIZER
is executed after the provider from APP_BASE_HREF
That causes, that the BASE_HREF
is not set.
回答2:
We had the same challenge: Set the APP_BASE_HREF
dynamically, based on a result from an async API call to allow routing of an app which can be accessed through different URLs.
While the solution presented by Günter looks sweet, it unfortunately did not work, at least with Angular 7. In our case, APP_BASE_HREF
always took precedence over APP_INITIALIZER
, so we couldn’t initialize the APP_BASE_HREF
based on the resolved promise value returned from the initializer.
Instead, I implemented the API call to happen before the Angular bootstrapping and then injected the provider so that it’s available within the Angular context.
Adding to main.ts
:
fetchConfig().then(config => {
platformBrowserDynamic([ { provide: ConfigData, useValue: config } ])
.bootstrapModule(AppModule)
.catch(err => console.log(err));
});
We can then configure the APP_BASE_HREF
in the providers
within app.module.ts
:
providers: [
// …
{
provide: APP_BASE_HREF,
useFactory: (config: ConfigData) => config.base,
deps: [ ConfigData ]
}
]
[edit 2019-08-21] Clarification per the comments: fetchConfig()
is the API request which gets the configuration and returns a Promise
. And ConfigData
is not an Angular service, but just a simple class which gets instantiated in fetchConfig()
and which gives me type safety when accessing it later in my application:
function fetchConfig (): Promise<ConfigData> {
return fetch('/api/config')
.then(response => response.json())
.then(response => new ConfigData(response));
}
回答3:
You can use APP_INITIALIZER
to get the path in advance and then use a dependency as shown in Angularjs2 - preload server configuration before the application starts
export function loadConfig(config: ConfigService) => () => config.load()
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule,
routes,
FormsModule,
HttpModule],
providers: [
ConfigService,
BackendRequestClass,
{ provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [ConfigService],
multi: true },
{ provide: APP_BASE_HREF, useFactory: (config) => config.appBaseHref, deps: [ConfigService] }
],
bootstrap: [AppComponent]
})
export class AppModule { }
The ConfigService
can inject BackendRequestClass
or Http
and fetch the data and then make it available using its appBaseHref
property (just an example how it could be done).
来源:https://stackoverflow.com/questions/46190280/angular-2-set-app-base-href-with-a-value-from-a-promise-observable