0

In my Angular 8 project, I have a UserService that requests the current User from the server using HttpClient and asynchronously assigns the response to its public user field. I inject a UserService into AppComponent and in its ngOnInit I copy this.userService.user into its own user field, which is bound to the content of a span defined in its HTML template file. In order to force Angular finish loading the User before ngOnInit is called, I implemented the Resolve<User> interface in UserService and set it as the resolver of the root route ("").

My problem is that when the application is started, AppComponent.ngOnInit is called before the router is activated and the resolver loads the User from the server, so AppComponent cannot display the loaded User in its HTML. Is it possible to load data before the bootstrapped component (AppComponent) is loaded, that is, before its ngOnInit method is called?

kol
  • 27,881
  • 12
  • 83
  • 120
  • 1
    Did you use a route Guard ? Did you try to use RxJS Subject to get user ? – ibenjelloun Feb 05 '20 at 15:24
  • @ibenjelloun No, I don't use route guards. And no, I don't use RxJS Subject - I implemented Resolve.resolve() in UserService, which does load the User when the router is activated. The problem is that the router is activated only after AppComponent is loaded. – kol Feb 05 '20 at 15:28
  • 1
    I support @ibenjelloun comment, easiest way to handle this is to subscribe in your `OnInit` hook on an Observable bound to user request, not to force Angular to wait the answer of an asynchronous call to load your `AppComponent` . – Mozgor Feb 05 '20 at 15:32
  • @Mozgor Thanks, in the end, I "embraced the async way". – kol Feb 05 '20 at 18:03

1 Answers1

1

You can do it with APP_INITIALIZER, a function that will be executed before an application is initialized

https://angular.io/api/core/APP_INITIALIZER

In your app.module.ts

export function initializeConfig(initService: InitService) {
  const x = (): Promise<any> => {
    return initService.Init();
  };
  return x;
}

@NgModule({
  ...
  providers: [
    InitService,
    {
      provide: APP_INITIALIZER,
      useFactory: initializeConfig,
      deps: [InitService],
      multi: true
    },
  ],
  ...
})

init.service.ts

@Injectable()
export class InitService {

  constructor(private service: YourService) {
  }

  Init() {
    return new Promise<void>((resolve, reject) => {
      this.service.loadDataBeforeBootstrap.then( () => {
        resolve();
      }).catch( error => {
        reject(error);
      });
    });
  }
}
Fmerco
  • 1,160
  • 5
  • 20