You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular使用*ngIf控制Chart.js容器时报无法获取上下文错误如何解决

报错原因

*ngIf指令的逻辑是当绑定条件为false时,会直接将对应元素从DOM树中移除,不会进行渲染。你在ngOnInit生命周期中初始化Chart实例时,默认showAna为false,id为chart的canvas元素还没有被渲染到页面中,Chart.js无法获取到对应的画布上下文,因此抛出该错误。
当你移除*ngIf时,canvas元素在页面初始化时就会渲染,因此初始化Chart时可以正常找到对应元素,不会报错。

解决方案

你可以选择以下任意一种方式修复问题:

方案1:调整图表初始化时机(推荐)

将图表初始化逻辑从ngOnInit中抽离,仅在切换到图表标签时执行初始化,同时避免重复初始化图表实例:

修改后的TS代码:

// 新增变量标记图表是否已初始化
chartInited = false;

async ngOnInit(): Promise<void> {
  // 这里保留你原来获取表格和图表数据的逻辑
  // 不要在这里初始化Chart
  this.loading = false;
}

// 抽离图表初始化方法
initChart() {
  if (this.chartInited) return; // 避免重复初始化
  this.chart = new Chart('chart', {
    type: 'line',
    data: {
      labels: this.mesi,
      datasets: [{
        label: 'totale va ufficiali',
        data: this.totEffortva, 
        backgroundColor: [
          'rgba(255, 99, 132, 0.2)'],
        borderColor: [
          'rgba(255, 99, 132, 1)'],
        borderCapStyle: 'butt',
        borderDash: [],
        borderDashOffset: 0.0,
        borderJoinStyle: 'miter',
        pointBorderColor: "white",
        pointBackgroundColor: "black",
        pointBorderWidth: 1,
        pointHoverRadius: 8,
        pointHoverBackgroundColor: "brown",
        pointHoverBorderColor: "yellow",
        pointHoverBorderWidth: 2,
        pointRadius: 4,
        pointHitRadius: 10,
      },{
        label: "totale giornate impegnate",
        fill: true,
        lineTension: 0.1,
        backgroundColor: "rgba(167,105,0,0.4)",
        borderColor: "rgb(167, 105, 0)",
        borderCapStyle: 'butt',
        borderDash: [],
        borderDashOffset: 0.0,
        borderJoinStyle: 'miter',
        pointBorderColor: "white",
        pointBackgroundColor: "black",
        pointBorderWidth: 1,
        pointHoverRadius: 8,
        pointHoverBackgroundColor: "brown",
        pointHoverBorderColor: "yellow",
        pointHoverBorderWidth: 2,
        pointRadius: 4,
        pointHitRadius: 10,
        data: this.totprog,
        spanGaps: false,
      }]
    },
    options: {
      responsive: true,
      plugins: {
        legend: {
          position: 'top',
        },
        title: {
          display: true,
          text: 'Chart.js Line Chart'
        }
      }
    },
  });
  this.chartInited = true;
}

ana(show:boolean){
  this.showAna = show;
  // 切换到图表标签时初始化图表
  if(show && !this.loading) {
    this.initChart();
  }
}

修改后的HTML代码:

删除canvas标签内的{{chart}},该写法无实际作用还可能干扰画布渲染:

<div>
  <button class="tablink" style="float: left;" (click)="ana(false)">DATI TABELLARI</button>
  <button class="tablink" style="float: right;" (click)="ana(true)">GRAFICO</button>
</div>
<div *ngIf="showAna!=true && loading==false">
 TABLES
</div>
<div *ngIf="showAna==true && loading==false">
    CHART
    <div id="divCh">
        <canvas id="chart"></canvas>
    </div>
</div>

方案2:使用[hidden]代替*ngIf(改造成本最低)

[hidden]指令仅会控制元素的显示隐藏,不会将元素从DOM中移除,因此页面初始化时canvas元素存在,可正常初始化Chart:

<div>
  <button class="tablink" style="float: left;" (click)="ana(false)">DATI TABELLARI</button>
  <button class="tablink" style="float: right;" (click)="ana(true)">GRAFICO</button>
</div>
<!-- 条件和*ngIf相反,hidden为true时隐藏元素 -->
<div [hidden]="showAna==true || loading==true">
 TABLES
</div>
<div [hidden]="showAna!=true || loading==true">
    CHART
    <div id="divCh">
        <canvas id="chart"></canvas>
    </div>
</div>

TS代码无需调整,仅需要删除canvas内的{{chart}}即可。

内容的提问来源于stack exchange,提问作者pietro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 03:15:03