Using Resolve In Angular2 Routes

In Angular 1 my config looks like this:

$routeProvider
  .when("/news", {
    templateUrl: "newsView.html",
    controller: "newsController",
    resolve: {
        message: function(messageService){
            return messageService.getMessage();
    }
  }
})

How to use resolve in Angular2?


Based on @angular/router v3-beta, these are the required steps.

Implement a resolver that returns an Observable or a plain value:

@Injectable()
export class HeroResolver implements Resolve {

    constructor(
        private service: HeroService
    ) {}

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Hero> {
        const id = +route.params['id'];
        return Observable.fromPromise(this.service.getHero(id));
    }

}

Note that in case you return an observable, the unwrapped value (first one) will be available through route.snapshot.data. If you want the observable itself to be available, then you need to wrap it in another Observable:

return Observable.of(source$);

Add the resolver to your route:

export const HeroesRoutes: RouterConfig = [
    { path: 'heroes',  component: HeroListComponent, resolve: { heroes: HeroesResolver } },
    { path: 'hero/:id', component: HeroDetailComponent, resolve: { hero: HeroResolver } }
];

Finally, provide your resolve class and any dependency to bootstrap or your main component providers:

bootstrap(AppComponent, [
    HeroesResolver, HeroService
])

Consume the resolved data from an ActivatedRoute instance:

ngOnInit() {
    this.hero = this.route.snapshot.data['hero'];
}

Remember that snapshot means the value at the state of execution, both in the component class and the resolver class. Data can't be refreshed from params updates with this approach.

Plunker: http://plnkr.co/edit/jpntLjrNOgs6eSFp1j1P?p=preview Source material: https://github.com/angular/angular/commit/f2f1ec0#diff-a19f4d51bb98289ab777640d9e8e5006R436


As alexpods has already mentioned, there doesn't seem to be a 'resolve' as such. The idea seems to be that you make use of the lifecycle hooks that the router provides. These are:

  • canReuse
  • canDeactivate
  • onActivate
  • onReuse
  • onDeactivate

Then there is @CanActivate. This is a special hook because it is called before your component is instantiated. Its parameters are (next, previous) which are the components you're routing to and the component you've come from (or null if you have no history) respectively.

import {Component} from '@angular/core';
import {ROUTER_DIRECTIVES, CanActivate, OnActivate} from '@angular/router';

@Component({
    selector: 'news',
    templateUrl: 'newsView.html',
    directives: [ROUTER_DIRECTIVES]
})

@CanActivate((next) => {
    return messageService.getMessage()
        .then((message) => {
            next.params.message = message;
            return true; //truthy lets route continue, false stops routing
        });
})

export class Accounts implements OnActivate {

    accounts:Object;

    onActivate(next) {
        this.message = next.params.message;
    }
}

The thing I have not figured out yet is how to get the result of the promise into your onActivate - other than storing it on your 'next' component. This is because onActivate is also only invoked with next and previous and not the result of the promise. I'm not happy with that solution but it's the best I could come up with.


https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html "resolve" has been brought back to angular2 router, but the documentation is sparse.

Example:

class TeamResolver implements Resolve {
  constructor(private backend: Backend) {}
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<any> {
    return this.backend.fetchTeam(this.route.params.id);
  }
}
bootstrap(AppComponent, [
  TeamResolver,
  provideRouter([{
    path: 'team/:id',
    component: TeamCmp,
    resolve: {
      team: TeamResolver
    }
  }])
);