[英]Child component not updating on parent route change
I have been trying to learn angular 2 following along with this tutorial [Build an application with Angular 2 and Firebase][1]
and trying to extend on it.我一直在尝试按照本教程[Build an application with Angular 2 and Firebase][1]
来学习 angular 2,并尝试对其进行扩展。 But I have hit a snag when trying to nest multiple routes.但是我在尝试嵌套多条路线时遇到了障碍。
App structure:应用结构:
Goals – (has router-outlet)
> Single Goal with Experiments list – (has router-outlet)
> Single Experiment – (has router-outlet)
> Experiment Notes
Router setup:路由器设置:
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' }
];
The Problem问题
If I click on Experiment 1 in the Experiment List I got to goals/1/experiments/1/notes
the url is correct and I see the correct Experiment 1's Notes .如果我在实验中点击实验1列出我到goals/1/experiments/1/notes
的URL是正确的,我看到正确的实验1的注意事项。
If I then click on Experiment 2 in the Experiment List goals/1/experiments/2/notes
the url is correct the experiment details are correct but the notes are still Experiment 1's Notes .如果我再在实验列表点击实验2 goals/1/experiments/2/notes
的URL是正确的实验细节是正确的,但在纸币仍在实验1和的注意事项。
If I then refresh the browser, Experiment 2 to loads and the notes are now Experiments 2's Notes which is correct.如果我然后刷新浏览器,将加载实验 2 ,注释现在是正确的实验 2 的注释。
This is how I get the experimentId
for retrieving the notes这就是我如何获得用于检索笔记的experimentId
ID
experiment-notes.component.ts实验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);
I'm sure it's an obvious mistake I'm making but for the life of me I can't see where I am going wrong with this.我确信这是我犯的一个明显的错误,但对于我的生活,我看不出我哪里出错了。
This is because the ngOnInit() method is only calling once during creating the component.这是因为 ngOnInit() 方法在创建组件期间只调用一次。 When u click on Experiment 2, you don't create a new experiment-component.当您单击实验 2 时,您不会创建新的实验组件。 You just use the old one.你只用旧的。
The Url is changing because you are still subscribed on the route params. Url 正在更改,因为您仍然订阅了路由参数。 But your Service call is out of the Observable.但是您的 Service 调用不在 Observable 中。 SO just put the service call into your obserable, then everytime when the route param is changed, it will load the new data.所以只需将服务调用放入您的可观察对象中,然后每次更改路由参数时,它都会加载新数据。
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);
});
The API has changed quite a bit in the latest version angular 5.2.5 As Emre says the problem is that ngOnInit is called only once when the child component is first created, after creation the component needs to be notified of changes to the url so that it can fetch the parameter again, this can be done by adding a listener on the Router object and then using the route object to get the part required. API 在最新版本的angular 5.2.5 中发生了很大变化 正如 Emre 所说,问题是 ngOnInit 在第一次创建子组件时只调用一次,创建后需要通知组件 url 的更改,以便它可以再次获取参数,这可以通过在 Router 对象上添加一个侦听器然后使用路由对象来获取所需的部分来完成。 Here is some example code based on the tour of heroes sample app:下面是一些基于英雄之旅示例应用程序的示例代码:
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();
}
}
The most relevant parts are in ngOnInit()最相关的部分在ngOnInit()
activatedRoute has parent property. activateRoute 具有父属性。 Simply need to subscribe to params in children component like below:只需要订阅子组件中的参数,如下所示:
this.route.parent.params.subscribe((params: Params) => {
// some stuff
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.