如何在基于* ngIf条件加载的模板中定位元素

时间:2019-03-23 09:33:59

标签: html angular

我正在尝试通过模板变量将模板中的元素作为目标,但它始终返回未定义的值。

当您导航到应用程序中的某个路由时,我的组件会从rxjs的forkJoin方法内部获取一些数据。数据很多,连接速度很慢,所以有2秒的延迟,因此,我处于中间状态,显示加载微调器,然后在所有数据返回时消失。

我的模板代码看起来像...

<div class="container" *ngIf="ready; else loading">
   <mat-horizontal-stepper labelPosition="bottom" #stepper>
      <mat-step label="Step 1"> Step 1 Content... </mat-step>
      <mat-step label="Step 2"> Step 2 Content... </mat-step>
      <mat-step label="Step 3"> Step 3 Content... </mat-step>
   </mat-horizontal-stepper>
</div>

<ng-template #loading>
   <mat-spinner></mat-spinner>
</ng-template>

我的component.ts文件看起来像这样...

public ready = false;
public dataset1;
public dataset2;
@ViewChild('stepper') private myStepper: MatStepper;

constructor(private dataService: DataService) {}

ngOnInit() {
   this.fetch();
   console.log(this.myStepper); // returns undefined
}

ngAfterViewInit() {
   console.log(this.myStepper); // also returns undefined
}

public fetch() {
   return forkJoin(
      this.dataService.getDataSet1(),
      this.dataService.getDataset2()
   ).subscribe(res => {
      this.dataset1 = res[0];
      this.dataset2 = res[1];
      this.ready = true;
   }, error => console.log('Error : ', error));
}

我希望能够定位步进器并获取步骤总数,并根据某些用户活动使用这些步骤导航到另一个步骤,但是如果我一直不确定,我将无法做到这一点。 我该如何解决?

1 个答案:

答案 0 :(得分:3)

因为您将其保存在* ngIf块中,所以除非* ngIf有条件,否则您将无法访问它,因为此伪指令直到它为true时才加载html元素,包括步进器。这意味着您可以检查以下代码段中添加了该值的位置。至此,您将ready变量设置为true意味着html的这一部分也将可用。这可能是调用函数运行逻辑的好方法。

如评论中所述,理想的是在尝试访问之前调用更改检测。这可以通过通过构造函数注入ChangeDetectorRef来完成。

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

确保以上导入内容均包含ChangeDetectorRef。

constructor(private ref: ChangeDetectorRef,
            private dataService: DataService) {}

public fetch() {
   return forkJoin(
      this.dataService.getDataSet1(),
      this.dataService.getDataset2()
   ).subscribe(res => {
      this.dataset1 = res[0];
      this.dataset2 = res[1];
      this.ready = true;

      this.ref.detectChanges();
      console.log(this.stepper); // you will be able to read it here.

}, error => console.log('Error : ', error));

This article helps explain the dom behaviour with *ngIf

要考虑的其他事情是使用ViewChild的setter,这意味着仅当* ngIf为true时才设置该值。意味着一旦在dom中提供它,它将立即可用。这是获得参考的好方法,并且看起来像。最初还将使用undefined进行设置,直到运行更改检测或手动运行更改检测为止。

public myStepper: MatStepper;

@ViewChild('stepper') set content(content: MatStepper) {
    this.myStepper = content;
}

这样,您可以引用ViewChild并通过this.myStepper与之交互。