Using Resolve In Angular2 Routes

前端 未结 5 796
盖世英雄少女心
盖世英雄少女心 2020-11-27 15:05

In Angular 1 my config looks like this:

$routeProvider
  .when(\"/news\", {
    templateUrl: \"newsView.html\",
    controller: \"newsController\",
    resol         


        
相关标签:
5条回答
  • 2020-11-27 15:56

    You can create your Resolver in Angular2+ and apply it to the router quite easily. look at the below, here is the way to create the Resolver in Angular:

    @Injectable()
    export class AboutResolver implements Resolve<Message> {
    
      constructor(private aboutService: AboutService, private router: Router) {}
    
      resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
        const id = route.params['id'];
        return this.aboutService.getById(id);
      }
    }
    

    then in the router config:

    export const Routes: RouterConfig = [
      { path: 'about',  component: AboutComponent, resolve: { data: AboutResolver } }
    ]; 
    

    and finally in your component:

    ngOnInit() {
      this.route.data.subscribe((data: { about: About }) => {
        this.about = data.about;
      });
    }
    
    0 讨论(0)
  • 2020-11-27 16:05

    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
        }
      }])
    );
    
    0 讨论(0)
  • 2020-11-27 16:06

    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.

    0 讨论(0)
  • 2020-11-27 16:08

    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

    0 讨论(0)
  • 2020-11-27 16:10

    @AndréWerlang's answer was good, but if you want the resolved data on the page to change when the route parameter changes, you need to:

    Resolver:

    @Injectable()
    export class MessageResolver implements Resolve<Message> {
    
      constructor(private messageService: MessageService, private router: Router) {}
    
      resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Message> {
        const id = +route.params['id'];
        return this.messageService.getById(id);
      }
    }
    

    Your component:

    ngOnInit() {
      this.route.data.subscribe((data: { message: Message }) => {
        this.message = data.message;
      });
    }
    
    0 讨论(0)
提交回复
热议问题