Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Routing Module loads before APP_INITIALIZER

I have a value that is from of a config file from static AppConfigService. Described below:

reference code/article: https://blogs.msdn.microsoft.com/premier_developer/2018/03/01/angular-how-to-editable-config-files/

import { Injectable } from '@angular/core';
import { AppConfig } from './app-config';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment';

@Injectable()
export class AppConfigService {

static settings: AppConfig;
constructor(private http: HttpClient) { }
load() {
    console.log('is this getting fired before routing module check?');
    const jsonFile = `assets/config/config.${environment.name}.json`;
    return new Promise<void>((resolve, reject) => {
        this.http.get(jsonFile)
            .toPromise()
            .then((response: AppConfig) => {
                AppConfigService.settings = <AppConfig>response;
                console.log(AppConfigService.settings);
                resolve();
            })
            .catch((response: any) => {
                reject(`Could not load file '${jsonFile}': 
${JSON.stringify(response)}`);
            });
    });
}

}

This config gets loaded in my APP_INITIALIZER in the app.module.ts

  providers: [
    AppConfigService,
    {
      provide: APP_INITIALIZER,
      useFactory: (appConfigService: AppConfigService) => () => {appConfigService.load() },
      deps: [AppConfigService], multi: true
    }
  ],

but my routing module, named AppRoutingModule is reading something out of my AppConfigService.settings variable which is crazy enough, UNDEFINED. My application crashes. I expect the APP_INITIALIZER to fire BEFORE AppRoutingModule but this is not the case:

Uncaught TypeError: Cannot read property 'oldUrl' of undefined

oldUrl is a property of AppConfigService.settings. I checked if AppConfigService.settings is set, it IS, properly AFTER routing module is fired but this is not what I want.

I checked some other sources for help. I used the following already as maybe a fix: https://github.com/angular/angular/issues/14615 and https://github.com/angular/angular/issues/14588

@component({})
class App {
constructor(router: Router, loginService: LoginService) {
loginService.initialize();
router.initialNavigation();
}
}

@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(routes, {initialNavigation: false})
],
declarations: [ App ],
bootstrap: [ App ],
providers: [ Guard, LoginService ]
})
export class AppModule {
}

Unfortunately, the above solution is not fixing my problem. I also tried to put in AppModule but alas, that didn't help either.

Any help is very welcome.

like image 679
Danny Hoeve Avatar asked Dec 06 '18 10:12

Danny Hoeve


1 Answers

I've solved my App Initialization and Routing with NgRx listening the central state to know when the system is Loaded and activating the route Guards after that.

But for a direct solution, you need to add a Route Guard checking when your service is loaded. So, add a loaded: boolean flag in your Service, and check it from a Guard like this: https://github.com/angular/angular/issues/14615#issuecomment-352993695

This is better handled with Observables tho, and I'm wiring all with NgRx in my Apps using Facades to facilitate everything: https://gist.github.com/ThomasBurleson/38d067abad03b56f1c9caf28ff0f4ebd

Best regards.

like image 160
Mateo Tibaquira Avatar answered Oct 19 '22 08:10

Mateo Tibaquira