Search code examples
angularresolveresolverangular4-router

Resolve function does not resolve component data before the component ngOnInit function is invoked


I have a URL that is something like this:

base_path/some_path?elementId=33203

Basically, a user can and generally navigates to this path by pasting the above link in the browser. I need to load the data for this component before the component so I started reading up on the Angular routing tutorial, specifically, the resolver services that aim to achieve the exact quandry I possess. So I created a resolver service such as:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<SomeObject> {
    let loanId = route.queryParams['elementId'];

    if (isNil(loanId)) {
      return null;
    }
    return this.service.getElementById(elementId)
      .subscribe(response => {
    //response is JSON
          return Observable.of(response);
        }
        else {
          return null;
        }
      });
  } 

This resolve class is now added to the app.routing.module.ts like:

{ path: 'base_path/some_path', component: SomeComponent,
resolve : {
  someObject: SomeObjectResolver
}

}

And make the corresponding changes in my component.ts file, such as:

ngOnInit() {
     this.route.data.subscribe((data: { someObject: SomeObject}) => {

     });

}

I setup debug breakpoints in the resolver and component file. When I visit the URI: base_path/some_path?elementId=33203, it hits the resolver first, but since the resolver invokes the service (which in turn invokes an ajax call to the server fetch data), it then simply proceeds to the component, and invokes the ngOnInit function, tryin to invoke the subscribe function on (data: { someObject: SomeObject})

However, someObject is not yet available, so it throws an error and redirects.

What am I missing? Isn't the resolve function supposed to explicitly load the data for it's component before it is invoked?


Solution

  • You have to return an Observable, you don't need to subscribe to it and then return a new observable

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<SomeObject> {
      let loanId = route.queryParams['elementId'];
    
      if (isNil(loanId)) {
        return Observable.of(null);
      }
      return this.service.getElementById(elementId);
    }