简体   繁体   English

子组件未在父路由更改时更新

[英]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.

相关问题 append 子组件路由到父组件路由 - append child component route to the parent component route Angular 2 RC1-从子路径组件属性更新父组件属性 - Angular 2 RC1 - Updating parent component property from child route component property Angular:如何根据父应用程序组件的路由更改重新渲染子组件? - Angular: How to re-render a child component based on route change of parent app component? 父组件中的 Angular 2 routerLink 相对于子路由? - Angular 2 routerLink in parent component relative to child route? Angular默认子路由未加载父组件 - Angular default child route not loading parent component 角度2-子路径的父组件与父组件不同 - Angular 2 - Child route have a different parent component to parent component 重载子组件路由重载父父组件 - Reloading child component route reloads the parent parent component 为什么 Angular 子组件(导航栏)在路线更改后停止更新视图? - Why Angular child component ( navbar ) stops updating view after route change? Angular 的子组件中的父变量未更新 - The Parent Variable is not updating in the child Component in Angular 如何根据路由更改父组件上的标头 - How to change the header on parent component according to route
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM