加载dom元素后调用函数

时间:2019-03-05 23:32:50

标签: angular typescript

所以我有一个div元素(画布),该元素正在异步管道后面加载。加载画布后,我需要用一个名为loadChart()的函数填充它。我需要在canvas元素加载后调用该函数。我已经搜索了很多,但找不到很多东西,除了我需要使用一个实现AfterViewInit的指令,并在div元素加载后使用一个ngAfterViewInit()来调用所需的函数。我(很可能)正以错误的方式来对待这个问题,但是如果有人有任何想法,我想向正确的方向提供一些指导。

Home.component.ts

import { Component, OnInit} from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../../services/authentication/auth.service';
import { ComputationService } from '../../services/computation/computation.service';
import {map, tap} from 'rxjs/operators';
import {Observable} from 'rxjs';
import { Chart } from 'chart.js';
import { ViewChild, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit, AfterViewInit {

  units: Observable<Array<any>>;
  unitsData: Array<any>;
  occupancy: number;
  vacancy: number;
  chart: Chart;
  constructor(private route: Router, public authService: AuthService, private computationService: ComputationService) { }

  ngOnInit() {
    this.loadData();
  }

  @ViewChild('canvas') canvas: HTMLCanvasElement;

  ngAfterViewInit() {
    this.loadCharts();
  }

  loadData() {
    this.units = this.authService.getData().pipe(
      tap((results: any) => {
        if (results.success === true) {
          this.UnitsData = results.data;
          this.occupancy = Math.round(this.computationService.findOccupancy(this.unitsData) * 10000) / 100;
          this.vacancy = Math.round(this.computationService.findVacancy(this.unitsData) * 10000) / 100;
        }
      }),
      map((results: any) => results.data)
    );
  }

  loadCharts() {
    const ctx = this.canvas.getContext('2d');
    this.chart = new Chart(ctx, {
      type: 'doughnut',
      data: {
        labels: ['Occupied', 'Vacant'],
        datasets: [{
          data: [this.occupancy, this.vacancy]
        }]
      },
      options: {}
    });
  }
}

home.component.html

<div *ngIf="(units | async) as units; else loading">
  <mat-card-content>
    <canvas #canvas></canvas>
    <h2>{{occupancy}}% occupied</h2>
    <h2>{{vacancy}}% vacant</h2>
  </mat-card-content>
</div>
<ng-template #loading>
  <mat-spinner></mat-spinner>
</ng-template>

1 个答案:

答案 0 :(得分:0)

您的问题可能是在您的ngAfterViewInit时,可观察到的单位尚未发出真实值。因此,您的画布尚不可用。

您可以使用@ViewChild而不是@ViewChildren来为您提供QueryList的画布元素。 QueryList有一个changes可观察的。有了它,您可以在将画布添加到视图中的瞬间做出反应。

另一种选择是将同步内容提取到另一个组件中,在这里您可以使用画布onViewInit,并且可以像以前一样使用ViewChild。