【问题标题】:Navigating between child routes using Resolve in Angular 2 returns to first child在 Angular 2 中使用 Resolve 在子路由之间导航返回到第一个子路由
【发布时间】:2017-11-25 12:38:23
【问题描述】:

我们正在使用 Angular 路由器 4.0.0,并且在我们的一个路由中,我们实现了路由器解析器服务,以便在更改路由时向组件提供数据。

但是,当使用 this.router.navigate(绝对或相对,没关系)从 job/1/items 导航到 job/2/items 时,路径会暂时更改为新路径 (2),但随后回到旧的(1)。请注意,在解析服务的解析方法实现中永远不会遇到错误。

我们的路由模块:

@NgModule({
    imports: [
        RouterModule.forChild([
            { path: "", redirectTo: "all", pathMatch:"full"},
            {
                path: "all",
                canActivate: [AuthGuard],
                component: JobsListComponent,
                data: { title: 'jobs', listId: 'all', listTitle: 'AllJobs' }
            },
            {
                path: ':id',
                canActivate: [AuthGuard],
                component: JobDetailComponent,
                resolve: { detailData: JobDetailResolve },
                children: [
                    { path: '', redirectTo: 'feed', pathMatch: 'full' },
                    { path: 'feed', component: JobDetailFeedComponent, data: { title: 'feed', isDetail: true } },
                    { path: 'items', component: JobDetailItemsComponent, data: { title: 'items', isDetail: true } },

                ]
            },
        ])
    ],
    exports: [
        RouterModule
    ],
    providers: [
        JobDetailResolve
    ]
})
export class JobsRoutingModule { }

我们的解决服务:

@Injectable()
export class JobDetailResolve implements Resolve<JobWithMetadata> {
    constructor(private jobsService: JobsService,
        private router: Router) { }

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<JobWithMetadata> {
        return Observable.create(observer => {
            var jobId = route.params["id"];
            this.jobsService.getJob(jobId).subscribe(
                detailData => {
                    var data = new JobWithMetadata(detailData.Job, detailData.JobMetadata, detailData.Job.Number);
                    observer.next(data);
                    observer.complete();
                }, error => {
                    error.subscribe(data => {

                        this.router.navigate([AppRoutes.Home,AppRoutes.Jobs]);
                        observer.next(null);
                        observer.complete();
                    });
                });
        });
    }
}

最后是组件内部的代码,在这种情况下,是在点击子组件内部的链接时,输入goToJob2:(click)="goToJob2()"

在 JobDetailItemsComponent 里面我们有上面提到的方法:

ngOnInit() {
       this.route.data
        .subscribe((data: { detailData: JobWithMetadata }) => {
            this.job = data.detailData.Job;
            this.initComponent();   // refreshes the component data  
        });
  }

goToJob2() {
    this.router.navigate([AppRoutes.Home, AppRoutes.Jobs, "2", "items"]);
}

首先将更改路由到jobs/2/items,但不知何故它返回到jobs/1/items。

对此有何建议?

谢谢

【问题讨论】:

    标签: angular angular2-routing


    【解决方案1】:

    在您的解析器代码中,您无需订阅错误。

        @Injectable()
        export class JobDetailResolve implements Resolve<JobWithMetadata> {
            constructor(private jobsService: JobsService,
                private router: Router) { }
    
            resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<JobWithMetadata> {
                return Observable.create(observer => {
                    var jobId = route.params["id"];
                    this.jobsService.getJob(jobId).subscribe(
                        detailData => {
                            var data = new JobWithMetadata(detailData.Job, detailData.JobMetadata, detailData.Job.Number);
                            observer.next(data);
                            observer.complete();
                        }, error => {
                            error.subscribe(data => {
    
                                this.router.navigate([AppRoutes.Home,AppRoutes.Jobs]);
                                observer.next(null);
                                observer.complete();
                            });
                        });
                });
            }
        }
    

    将您的代码重新格式化为

    @Injectable()
    export class JobDetailResolve implements Resolve<JobWithMetadata> {
        constructor(private jobsService: JobsService,
            private router: Router) { }
    
        resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<JobWithMetadata> {
            return Observable.create(observer => {
                var jobId = route.params["id"];
                this.jobsService.getJob(jobId).subscribe(
                    detailData => {
                        var data = new JobWithMetadata(detailData.Job, detailData.JobMetadata, detailData.Job.Number);
                        observer.next(data);
                    }, (error) => {
                        if(error) {
                            this.router.navigate([AppRoutes.Home,AppRoutes.Jobs]);
                            observer.next(null);
                            observer.complete();
                        }, () => {
                                   observer.complete();
                                 });
            });
        }
    }
    

    如果 JobService 使用 HttpClient 获取数据,那么默认情况下它提供了一个 promise / observable,因此您可以通过上述方式订阅它。当你订阅error时,没有error observable,错误来自http observable本身。希望这会有所帮助。

    如果你的服务是一个 http 调用,你也不需要 observable。相反,您可以这样做

    @Injectable()
    
        export class JobDetailResolve implements Resolve<any> {
         constructor(private service: Service) {}
         resolve(route: ActivatedRouteSnapshot) {
          return this.service.getJob(route.params["id"]).catch(() => {
            // Navigate here
          });
         }
        }
    

    由于 observable 是一个角度承诺,它会自动将数据发送到您的路由解析器

    {
                    path: ':id',
                    canActivate: [AuthGuard],
                    component: JobDetailComponent,
                    resolve: { detailData: JobDetailResolve },
                    children: [
                        { path: '', redirectTo: 'feed', pathMatch: 'full' },
                        { path: 'feed', component: JobDetailFeedComponent, data: { title: 'feed', isDetail: true } },
                        { path: 'items', component: JobDetailItemsComponent, data: { title: 'items', isDetail: true } },
    
                    ]
                }
    

    【讨论】:

      猜你喜欢
      • 2017-05-14
      • 1970-01-01
      • 2018-06-21
      • 2019-08-15
      • 1970-01-01
      • 1970-01-01
      • 2019-07-27
      • 2017-08-10
      • 2020-01-04
      相关资源
      最近更新 更多