开发者问题收集

Angular6 @ViewChild 与 ngIf 未定义

2019-04-10
32623

我在使用 @ViewChild 和通过 ngIf 显示的组件时遇到问题。我找到了各种解决方案,但没有一个对我有用。 这是我的主要组件,由各种步骤组成(为简洁起见,我在代码中只显示了 2 个步骤),带有一个用于向前导航的按钮和一个用于重置在第一步返回的组件的按钮。第一步显示在页面打开时:

...
<div class="my-container">
    <first-child *ngIf="showFirtChild"></first-child>
    <second-child *ngIf="showSecondChild"></second-child>
</div>
<button (click)="goToNextStep()"></button>
<button (click)="reset()"></button>
...
export class MainComponent implements OnInit {
    @ViewChild(FirstChild) private firstChildComp: MyFirstChildComponent;
    showFirtChild: boolean = true;

    ngOnInit() {
        //here firstChildComp is defined
    }

    //code for navigate through steps
    reset() {
        this.showFirtChild= true;
        this.firstChildComp.fillTable(); //fillTable is a function defined in MyFirstChildComponent
    }
...
}

在步骤导航期间,对 firstChildComp 的引用丢失,并且当调用 reset() 时,childComp 结果未定义。我知道原因是 ngIf,所以我尝试使用 ngAfterViewInit:

ngAfterViewInit() {
    this.fcomp = this.firstChildComp;
}

reset() {
        this.showFirtChild= true;
        this.fcomp .fillTable();
}

但它不能解决我的问题。 有什么建议吗?

3个回答

正如 Angular 的文档所述:

"True to resolve query results before change detection runs. If any query results are inside a nested view (such as *ngIf), the query is resolved after change detection runs."

因此,将参数 { static: false } 传递给 @ViewChild 可以解决问题,因为它是在 ngAfterViewInit 上访问的,而不是在变更检测运行之前在 ngOnInit 上访问的 { static: true } 。

Eduardo Mihalache
2019-12-13

ngIf 将从 DOM 中移除您的组件。因此它变为未定义的。 如果您改用 [hidden]="!showFirstChild" ,它将仅被隐藏,并将在组件中可用。

这里有一个 stackblitz ,您可以在其中检查这一点。

Felipe Gonçalves Marques
2019-04-10

尝试在其间运行变更检测,以确保 DOM 模板在重置更改后读取 DOM。

在模板中:

<first-child #firstChild *ngIf="showFirtChild"></first-child>

在控制器中:

import { ChangeDetectorRef } from '@angular/core';

export class exampleClass implements 
{

  @ViewChild('firstChild') public firstChildComp: MyFirstChildComponent;
  public fcomp: any;
  public showFirtChild: boolean;

  constructor(private ref: ChangeDetectorRef,
            //your services) {}

  public ngAfterViewInit() 
  {
      this.showFirtChild = true;
      this.ref.detectChanges();

      this.fcomp = this.firstChildComp;
  }

  public reset(): void 
  {
      this.fcomp.fillTable();
  }
}

ChangeDetectorRef 文档 以供进一步阅读。

dev-dan
2019-04-10