我正在尝试通过模板变量将模板中的元素作为目标,但它始终返回未定义的值。
当您导航到应用程序中的某个路由时,我的组件会从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));
}
我希望能够定位步进器并获取步骤总数,并根据某些用户活动使用这些步骤导航到另一个步骤,但是如果我一直不确定,我将无法做到这一点。 我该如何解决?
答案 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
与之交互。