【问题标题】:Angular 7 - Lazy loading with nested material tabsAngular 7 - 使用嵌套材质选项卡进行延迟加载
【发布时间】:2020-05-17 18:34:40
【问题描述】:

在我的 angular-7 项目中,我正在尝试制作一个带有嵌套材料选项卡的 html 页面,其中第二个选项卡将有另一组选项卡。在第二个选项卡中,尝试为传递给子组件的数据制作画布图表。

这是我的 html 代码。

<mat-tab-group mat-stretch-tabs [selectedIndex]="0">
    <mat-tab label="Sales"> Sales            
    </mat-tab>

    <mat-tab label="Purchase">
        <!-- <ng-template matTabContent>               //This block works but i want in tab format
            <div *ngIf="isReady " class="divinput ">
                <div *ngFor="let d of data">
                    <draw [input]="d "></draw>
                </div>
            </div>
        </ng-template> -->

        <mat-tab-group *ngIf="isReady">                   // this throws error
            <mat-tab *ngIf="isReady" label="north">
                <ng-template matTabContent>
                    <div *ngFor="let d of data">
                        <draw [input]="d"></draw>
                    </div>
                </ng-template>
            </mat-tab>
        </mat-tab-group>

    </mat-tab>
</mat-tab-group>

上面的代码调用了一个子组件“draw”,它具有绘制图表的功能。

private draw (chart){ 
    var canvas = <HTMLCanvasElement> document.getElementById(chart.id);
    var ctx = canvas.getContext("2d");
    return new Chart(ctx, {
        type: 'line',
        data: {labels: chart.x,datasets: mydata}
    }) 
}

这会引发错误,TypeError: Cannot read property 'getContext' of null for line var ctx = canvas.getContext("2d"); in function draw。看起来材料选项卡不等待数据可用。我试图通过“isReady”来处理这个问题,但没有运气。

我注意到一件奇怪的事情,当我将 [selectedIndex]="0" 更改为 [selectedIndex]="1" 时它会起作用。但不能将此视为第一个选项卡应根据要求在加载时处于活动状态。

我努力找出问题所在。请帮助解决问题。

【问题讨论】:

  • 您在设置 isReady = true 之前是否致电draw (chart)
  • draw(chart) if from child component and isReady is set in parent component and sent to child.
  • 忘记所有准备好的垃圾。只需使用 view child 并确保在 after view init 钩子之前不要在组件中调用 draw

标签: angular angular-material lazy-loading


【解决方案1】:

在 Angular 中,您可以使用 ViewChild 而不是 getElementById 来获取画布

在 Angular 7 中,它将按如下方式工作

example

component.html

<canvas #chart></canvas>

组件.ts

    import { Component, OnInit, ViewChild, ElementRef, Input } from '@angular/core';

    @Component({
      selector: 'app-draw',
      templateUrl: './draw.component.html',
      styleUrls: ['./draw.component.css']
    })
    export class DrawComponent implements OnInit {

      @ViewChild('chart')
      chartElementRef: ElementRef<HTMLCanvasElement>;

      @Input()
      input: any;

      constructor() { }

      ngOnInit() {
        this.draw();
      }

      private draw () { 
        const canvas = this.chartElementRef.nativeElement;
        const ctx = canvas.getContext("2d");
      }
    }

【讨论】:

  • 这将失败。在 after view init 钩子之前,视图子级不可用
  • @bryan60 不正确,在我的示例画布本身不在 ngIf 下,因此 ViewChild 将在 ngOnInit 之前设置它
  • 这是一种不太常见的情况......最佳实践是在 AfterViewInit 钩子之前不访问 ViewChild(ren)。那是它得到保证的时候:angular.io/api/core/ViewChild#description 和这里:angular.io/guide/lifecycle-hooks#afterview
  • 这也只能工作,因为你的闪电战是 Angular 7,它只提供静态查询。 8+ 默认为动态查询,并要求您将 static 显式设置为 true .. 我不明白为什么当您可以使用 afterViewinit 挂钩时,您的编码方式可能会因升级而中断
  • @bryan60 之所以有效,是因为 canvas 不是角度组件,也不是在组件生命周期中,它旨在说明它的使用方式。有人试图声称它是一个错误,但 Angular 团队添加了 static 属性而不是 github.com/angular/angular/issues/21800#issuecomment-360799520
猜你喜欢
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
相关资源
最近更新 更多