未更新父路由的子组件更改

时间:2016-11-11 12:55:49

标签: angular typescript angular2-routing angular2-router

我一直在尝试学习角度2以及本教程[Build an application with Angular 2 and Firebase][1],并尝试对其进行扩展。但是当我试图嵌套多条路线时,我遇到了麻烦。

应用结构:

Goals – (has router-outlet)
 > Single Goal with Experiments list – (has router-outlet)
  > Single Experiment – (has router-outlet)
   > Experiment Notes

路由器设置:

export const routerConfig : Route[] = [
  {
    path: 'goals',
    children: [
      {
        path: ':id', component: SingleGoalComponent,
        children: [
          {
            path: 'experiments',
            children: [
              { path: ':id', component: ExperimentDetailsComponent,
                children: [
                  { path: '', redirectTo: 'notes', pathMatch: 'full' },
                  { path: 'notes', component: ExperimentNotesComponent }
                ]
              },
              { path: 'new', component: NewExperimentComponent },
              { path: '' }
            ]
          },
          { path: '', redirectTo: 'experiments', pathMatch: 'full' }
        ]
      },
      { path: '', component: GoalsComponent }
    ]
  },
  { path: 'notes', component: NotesComponent },
  { path: '', redirectTo: 'goals', pathMatch: 'full' },
  { path: '**', redirectTo: 'goals', pathMatch: 'full' }
];

问题

如果我点击实验列表中的实验1 ,我得到了goals/1/experiments/1/notes,网址是正确的,我看到了正确的实验1的注释

如果我然后点击实验列表goals/1/experiments/2/notes中的实验2 ,网址是正确的,实验详细信息是正确的,但笔记仍然是实验1&#39}

如果我然后刷新浏览器,实验2 加载并且笔记现在是实验2的注释,这是正确的。

这就是我获取experimentId来检索笔记的方法

实验-notes.component.ts

experimentId: string;
  goalId: string;

  constructor(
    private router: Router,
    private route: ActivatedRoute,
    private experimentsService: ExperimentsService,
    private _location: Location) { }

  ngOnInit() {

    Observable.combineLatest(this.route.parent.params, this.route.parent.parent.params)
      .forEach((params: Params[]) => {
        this.experimentId = params[0]['id'];
        this.goalId = params[1]['id'];
      });

    console.log('Experiment ID: ' + this.experimentId + '| Goal Id: ' + this.goalId);

    this.notes$ = this.experimentsService.findAllNotesForExperiment(this.experimentId);

我确定这是我犯的一个明显的错误,但对于我的生活,我无法看到我在哪里出错。

3 个答案:

答案 0 :(得分:2)

这是因为在创建组件期间,ngOnInit()方法仅调用一次。当您单击实验2时,您不会创建新的实验组件。你只需使用旧的。

网址正在发生变化,因为您仍然订阅了路线参数。但您的服务电话不在Observable中。所以只需将服务调用放入您的服务中,然后每次更改路由参数时,它都会加载新数据。

ngOnInit() {

    Observable.combineLatest(this.route.parent.params, this.route.parent.parent.params)
      .forEach((params: Params[]) => {
        this.experimentId = params[0]['id'];
        this.goalId = params[1]['id'];

        console.log('Experiment ID: ' + this.experimentId + '| Goal Id: ' + this.goalId);
        this.notes$ = this.experimentsService.findAllNotesForExperiment(this.experimentId);
      });

答案 1 :(得分:2)

API在最新版本 angular 5.2.5 中发生了很大变化 正如Emre所说,问题是在首次创建子组件时只调用一次ngOnInit,创建后需要通知组件更改url以便它可以再次获取参数,这可以通过添加一个监听器来完成在Router对象上,然后使用route对象获取所需的部件。以下是基于英雄示例应用程序之旅的示例代码:

import {Component, Input, OnInit} from '@angular/core';
import {Hero} from '../hero';
import {HeroService} from "../hero.service";
import {ActivatedRoute, Router} from "@angular/router"; //Import Router and ActivatedRoute classes
import {Location} from '@angular/common';
import {MessageService} from "../message.service";

@Component({
  selector: 'app-hero-detail',
  templateUrl: './hero-detail.component.html',
  styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {
  @Input() hero: Hero;

  constructor(private route: ActivatedRoute,
              private heroService: HeroService,
              private messageService: MessageService,
              private location: Location,
              private router: Router) {
  }

  ngOnInit(): void {
    this.router.events.subscribe((val) => {//Use Router class to subscribe to events
      const id = +this.route.snapshot.paramMap.get('id');//When a route event occurs use the active route to update the parameter needed
      this.getHero(id);//Do what you would have initially done with the url value
    });
  }

  getHero(id): void {
    this.messageService.add(`HeroDetailComponent: fetching hero: ${id}`);
    this.heroService.getHero(id)
      .subscribe(hero => this.hero = hero);
  }

  goBack(): void {
    this.location.back();
  }
}

最相关的部分位于 ngOnInit()

答案 2 :(得分:0)

activatedRoute具有父属性。只需在子组件中订阅参数,如下所示:

this.route.parent.params.subscribe((params: Params) => {
  // some stuff
});