简体   繁体   English

满足ngIf条件时如何使用ViewChild获取HTML元素

[英]How to get the HTML element using ViewChild when ngIf condition is satisfied

I am having trouble with getting access to my canvas element when its *ngIf condition is satisfied.当满足 *ngIf 条件时,我无法访问我的画布元素。 Here is some context to understand the problem.这里有一些上下文可以理解这个问题。

In my application, I have a canvas element (that is initially hidden), and a ViewChild element ref variable in my typescript file that accesses the canvas.在我的应用程序中,我有一个画布元素(最初是隐藏的)和一个访问画布的打字稿文件中的 ViewChild 元素引用变量。 However, since the canvas is initially not rendered, the ViewChild element ref variable evaluates to undefined.但是,由于画布最初并未呈现,因此 ViewChild 元素 ref 变量的计算结果为未定义。 When the ngIf condition evaluates to true, the canvas is finally rendered but the ViewChild element ref variable is not updated.当 ngIf 条件评估为 true 时,最终呈现画布,但不会更新 ViewChild 元素 ref 变量。 In my code below, a floor plan from a database is loaded when the user chooses it.在我下面的代码中,当用户选择它时会加载数据库中的平面图。 The canvas will only be rendered once the floor plan is chosen (not null).只有在选择平面图(非空)后才会渲染画布。

How can I get the ViewChild element ref variable to recognize that the canvas is loaded so that it is not undefined when I want to use the canvas?如何让 ViewChild 元素 ref 变量识别画布已加载,以便在我想使用画布时它不是未定义的?

<div class="row" style="padding-left: 3rem;" *ngIf="floorPlan != null">
    <div class="col-lg-6 col-xl-6 col-md-12 col-sm-12" style="text-align: center;">
        <canvas (click)="onCanvasClick($event)" style="border: 1px solid lightgray;" #fpCanvas [ngClass]="{over: over}">
        </canvas> 
    </div>
</div>
@Component({
  selector: 'app-floor-plan',
  templateUrl: './floor-plan.component.html',
  styleUrls: ['./floor-plan.component.css']
})
export class FloorPlanComponent implements OnInit, AfterViewInit, AfterViewChecked {

  floorPlan: FloorPlan = null;
  imagePath : string = "";

  @ViewChild('fpCanvas', { static: true }) fpCanvas: ElementRef<HTMLCanvasElement>;

    ....


  constructor(private dataBaseManager: DatabaseManagerService) {
    this.dataBaseManager.loadedFloorPlanSubject.subscribe(loaded => {
      this.floorPlan = new FloorPlan(loaded);
      setTimeout(this.initCanvasAndContext, 2000)
      this._image.src = this.floorPlan.getImagePath();

    })


   ....

 chooseFloorPlan() {

    this.onToggleChooseFloorPlanDialog();
    this.dataBaseManager.fetchFloorPlan(this.selectedFloorPlanIndex)

  }




}

Answer only work for Angular 8+答案仅适用于 Angular 8+

First, change static: true to static: false首先,将static: true更改为static: false

@ViewChild('fpCanvas', { static: false}) fpCanvas: ElementRef<HTMLCanvasElement>;

Using ChangeDetectorRef to manually detect changes when floorPlan is updated.使用ChangeDetectorRef时,手动检测更改floorPlan进行更新。

this.floorPlan = new FloorPlan(loaded);
this.changeDetectorRef.detectChanges();

BTW, putting async logic inside the constructor is not a good approach.顺便说一句,将异步逻辑放在构造函数中并不是一个好方法。

Suggest move it to ngOnInit.建议将其移至 ngOnInit。

ngOnInit() {
    this.dataBaseManager.loadedFloorPlanSubject.subscribe(loaded => {
      this.floorPlan = new FloorPlan(loaded);
      this.changeDetectorRef.detectChanges();
      setTimeout(this.initCanvasAndContext, 2000)
      this._image.src = this.floorPlan.getImagePath();
    })
}

Please refer to the thread I put in the comment for detail.有关详细信息,请参阅我在评论中放置的线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM