码迷,mamicode.com
首页 > 其他好文 > 详细

[Angular2 Router] Resolving route data in Angular 2

时间:2016-11-16 07:45:51      阅读:439      评论:0      收藏:0      [点我收藏+]

标签:derby   strong   tar   one   service   stat   class   find   scom   

From Article: RESOLVING ROUTE DATA IN ANGULAR 2

Github

 

If you know Anuglar UI router, you must know resolve function in ui router, which you can load data before template and controller get inited. In Angular2 router, you can also use resovler. 

 

The recommended (personal preferred) way is use class to resolve the data, becasue you can inject servcie, so you can fetch data instead of hard cord data.

There is another way to use DI ‘useValue‘. Check out the article.

 

Create a resolver:

// hero-resolve.directive.ts


import {Resolve, ActivatedRouteSnapshot, RouterStateSnapshot} from "@angular/router";
import {Observable} from "rxjs";
import {StarWarsService} from "./heros.service";
import {Injectable} from "@angular/core";

@Injectable()
export class HeroDetailResolver implements Resolve<any> {

  constructor(private startWarsService: StarWarsService){

  }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | any{
    const id = route.params[id];
    return this.startWarsService.getPersonDetail(id);
  }

}

 

After create the resovler, you can add to the providers:

@NgModule({
  imports: [
    CommonModule,
    herosRoutes
  ],
  declarations: [HerosComponent, HeroComponent],
  providers: [StarWarsService, CanHeroDeactivate, CanHeroActivateDirective, HeroDetailResolver]
})

 

Routers:

import {HerosComponent} from "./heros.component";
import {RouterModule} from "@angular/router";
import {HeroComponent} from "./hero/hero.component";
import {CanHeroDeactivate} from "./heros-can-deactivate.directive";
import {CanHeroActivateDirective} from "./heros-can-activate.directive";
import {HeroDetailResolver} from "./hero-resolver.directive";
const routes = [
  {path: ‘‘, component: HerosComponent},
  {
    path: :id,
    component: HeroComponent,
    canDeactivate: [CanHeroDeactivate],
    canActivate: [CanHeroActivateDirective],
    resolve: {
      hero: HeroDetailResolver
    }
  },
];
export default RouterModule.forChild(routes)

Here ‘hero‘ will be used to fetch data from router data.

 

Component:

import {
  Component,
  OnInit,
  OnDestroy,
  ViewChild,
} from @angular/core;
import {ActivatedRoute, Router} from "@angular/router";
import {StarWarsService} from "../heros.service";
import {Observable, Subscription, BehaviorSubject} from "rxjs";

export interface Hero{
  name: string,
  image: string
}

@Component({
  selector: app-hero,
  templateUrl: hero.component.html,
  styleUrls: [hero.component.css]
})
export class HeroComponent implements OnInit, OnDestroy {

  @ViewChild(inpRef) input;

  heroId: number;
  hero: BehaviorSubject<Hero>;
  description: string;
  querySub: Subscription;
  routeParam: Subscription;
  editing: boolean = false;

  constructor(private route: ActivatedRoute,
              private router: Router,
              private starwarService: StarWarsService) {

  }

  ngOnInit() {

    /* // Old way to get data from service when component inited
    this.hero = new BehaviorSubject({name: ‘Loading...‘, image: ‘‘});

    this.route.params
     .map((p:any) => {
      this.editing = false;
      this.heroId = p.id;
      return p.id;
     })
     .switchMap( id => this.starwarService.getPersonDetail(id))
    .subscribe( this.hero);*/

    // Here using resolver instead of fetch on fly
    this.routeParam = this.route.params
      .map((p:any) => p.id)
      .subscribe( (id) => {
        this.editing = false;
        this.heroId = id;
      });
    this.hero = this.route.data
      .map((d:any)=> d[hero]);
  }

  ngOnDestroy() {
    this.querySub.unsubscribe();
    this.routeParam.unsubscribe();
  }
}

 

ONE important note that: If return Observable from resolver, the observable should completed! Otherwise, it doesn‘t work. So why in the exmaple, it works, because $http.get(), it complete itself. 

But if you use AngualrFire2, you fetch data from Firebase like:

  findLessonByUrl(url){
     return this.angularFireRef.database.list(lessons, {
      query: {
        orderByChild: url,
        equalTo: url
      }
    })
    .filter(r => !!r)
    .map(res => res[0]);
  }

The observable doesn‘t complete itself, so in the resolver, you need to find a way to make the observable completed. 

For example:

import {Resolve, RouterStateSnapshot, ActivatedRouteSnapshot} from "@angular/router";
import {Observable} from "rxjs";
import {CourseService} from "../course.service";
import {Injectable} from "@angular/core";

@Injectable()
export class LessonDataResolver implements Resolve {
  constructor(private lessonService: CourseService){

  }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
    const url = route.params[id];
    return this.lessonService.findLessonByUrl(url).first();
  }

}

Here it calls .first() to complete the observable. Or you can use ‘.take(1)‘.

[Angular2 Router] Resolving route data in Angular 2

标签:derby   strong   tar   one   service   stat   class   find   scom   

原文地址:http://www.cnblogs.com/Answer1215/p/5947852.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!