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

Angular组件中ng-repeat渲染Chart.js环形图重叠问题求助

Fixing Overlapping Doughnut Charts in Angular Component with Chart.js

Hey there, let's break down why your two doughnut charts are merging into one, and fix it step by step!

The Root Cause

The main issue here is how you're selecting the canvas element for Chart.js:

new Chart(document.getElementsByClassName("doughnut-chart"), { ... })

document.getElementsByClassName grabs all elements with that class across the entire page. When your ng-repeat renders multiple instances of your appSeveritiesComponent, the second component's chart initialization will target every matching canvas (including the first one) and overwrite it with its own data. That's why you end up with one chart showing combined (actually, overwritten) data.

Step-by-Step Fix

1. Use Component-Specific DOM Selection

Instead of querying the entire document, use Angular's $element service to only target the canvas inside the current component instance. First, inject $element into your controller.

2. Clean Up Chart Configuration

You also have a duplicate labels property in your Chart config (you first set it to Object.keys(that.severities), then overwrite it with { display: false }). The legend visibility belongs in the options section, not the data section.

Modified Controller Code

'use strict';
const appModule = angular.module('appModule');
appModule.component('appSeveritiesComponent', {
  templateUrl: '/app/components/severitiesComponent/severitiesComponent.html',
  controller: severitiesComponentController,
  bindings: { severities: '<' }
});

// Inject $element to access the component's DOM
severitiesComponentController.$inject = ["$timeout", "$element"];
function severitiesComponentController($timeout, $element) {
  var that = this;

  that.keys = function() {
    return Object.keys(that.severities);
  }
  $timeout(that.keys, 0);

  that.initChart = function() {
    // Get ONLY the canvas inside THIS component instance
    const canvas = $element.find('.doughnut-chart')[0];
    if (!canvas) return; // Exit if canvas isn't found

    // Prepare chart data
    that.arr = [];
    for (var key in that.severities) {
      that.arr.push(that.severities[key]);
    }

    new Chart(canvas, {
      type: 'doughnut',
      animationEnabled: true,
      responsive: true,
      data: {
        labels: Object.keys(that.severities),
        datasets: [{
          backgroundColor: ["rgb(213, 65, 65)", "rgb(243, 171, 16)", "rgb(65, 176, 213)"],
          data: that.arr
        }]
      },
      options: {
        plugins: {
          legend: {
            display: false // Correct place to hide the legend
          }
        }
      }
    });
  }

  $timeout(that.initChart, 0);

  // Optional: Update chart when severities data changes
  that.$onChanges = function(changes) {
    if (changes.severities && changes.severities.currentValue) {
      $timeout(that.initChart, 0);
    }
  }
}

Key Improvements

  • Component-Specific Selection: $element.find('.doughnut-chart') ensures each component only interacts with its own canvas, preventing overlaps.
  • Fixed Chart Config: Moved the legend visibility setting to options.plugins.legend where it belongs, removing the duplicate labels property.
  • Optional Data Update Handling: The $onChanges hook ensures your chart updates if the severities data passed from the parent changes (useful for async data loads).

With these changes, each component instance will render its own independent doughnut chart, no more overlapping or merged data!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:06:51