Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 Set APP_BASE_HREF with a value from a Promise / Observable

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

like image 344
Kevin Clerc Avatar asked Sep 13 '17 06:09

Kevin Clerc


2 Answers

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.

like image 121
Kevin Clerc Avatar answered Sep 22 '22 12:09

Kevin Clerc


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));
}
like image 40
qqilihq Avatar answered Sep 21 '22 12:09

qqilihq