无法读取angular6中的属性'parentNode'为null,charj js错误

时间:2018-12-27 04:08:20

标签: javascript angular angular6 chart.js angular2-routing

While navigating back to the home route, getting below error in chart js

core.js:1624 ERROR TypeError: Cannot read property 'parentNode' of null
    at Object.helpers._getParentNode (core.helpers.js:488)
    at Object.helpers.getMaximumWidth (core.helpers.js:495)
    at Chart.resize (core.controller.js:185)
    at listener (core.controller.js:815)
    at platform.dom.js:270
    at platform.dom.js:162
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:3748)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)

我在一页中有多个图表,并且为每个图表创建了单独的组件。我正在使用角度6的图表js。有两种不同的路线,并且图表显示在主页上。第一次加载图表时,它可以正常工作,但是当我从其他路线导航回来后返回首页时,控制台出现错误。我从API提取数据后销毁了图表(chart.destroy())。如果我删除销毁方法,则不会发生错误,但是我的图表使用的是旧实例,而未显示更新结果。

我已经使用路由出口在两个组件之间导航。 以下是该组件之一的示例代码:

export class deptChartComponent implements AfterViewInit, OnDestroy {
  selectedDeptName: string;
  selectedDeptId: string;
  deptList: any[];
  deptId: any[];
  dept = new FormControl();
  private canvas: any;
  context: any;
  private depthChartData: any[];
  private depthChart: Chart;
  TCR: number;
  displayDrawer: boolean = true;
  expandView: boolean = false;
  showTCR: boolean = false;
  lineId: string;
  showLoadBar: boolean = true;
  @Output()
  deptChartExpand: EventEmitter<boolean> = new EventEmitter();
  projectDataSubscription: Subscription = new Subscription();
  filteredDataSubscription: Subscription = new Subscription();
  deptChartDataSubscription: Subscription = new Subscription();
  constructor(
    private projectDataService: ProjectDataService,
    private filteredDataService: FilteredDataService,
    private deptChartDataService: deptChartDataService
  ) {}

  ngAfterViewInit() {
    this.getInitialData();
  }
  ngOnDestroy() {
    if (this.depthChart) {
      this.depthChart.destroy();
    }
    this.projectDataSubscription.unsubscribe();
    this.filteredDataSubscription.unsubscribe();
    this.deptChartDataSubscription.unsubscribe();
  }
  getInitialData() {
    this.filteredDataSubscription = this.filteredDataService.currentdeptId.subscribe(
      filteredData => {
        this.showLoadBar = true;
        if (filteredData.length >= 1) {
          this.filteredDataSubscription = this.filteredDataService.selectedStatus.subscribe(
            status => {
              this.projectDataSubscription = this.projectDataService
                .getFilterHeaderData(status)
                .valueChanges.subscribe(response => {
                  const initialdeptData = this.getdeptData(
                    response,
                    filteredData
                  );
                  const filtereddeptData = initialdeptData.filter(function(
                    dept
                  ) {
                    return filteredData.indexOf(dept.DeptId) >= 0;
                  });
                  if (filtereddeptData[0]) {
                    this.selectedDeptName = filtereddeptData[0].DeptName;
                    this.selectedDeptId = filtereddeptData[0].DeptId;
                    this.dept = new FormControl(this.selectedDeptName);
                  }
                  this.deptChartDataSubscription = this.deptChartDataService
                    .getdeptChartData(this.selectedDeptId)
                    .valueChanges.subscribe(deptChartData => {
                      this.showLoadBar = true;
                      if (deptChartData) {
                        this.buildChartResponse(deptChartData);
                        this.showLoadBar = false;
                      }
                    });
                });
            }
          );
        }
      }
    );
  }
  createChartConfig(chartData: any[]): Chart.ChartConfiguration {
    if (chartData === null) {
      return;
    }
    const chartConfig: Chart.ChartConfiguration = {
      type: chartParameters.LINE,
      data: {
        datasets: this.getChartDataSet(chartData)
      },
      options: {
        responsive: true,
        legend: {
          display: true
        },
        tooltips: {
          intersect: false,
          titleFontSize: 14,
          titleFontFamily: chartParameters.ARIAL,
          bodyFontSize: 30,
          footerFontSize: 12,
          footerFontFamily: chartParameters.ARIAL,
          footerFontColor: chartParameters.DATE_COLOR,
          cornerRadius: 0,
          caretSize: 0,
          displayColors: false,
          xPadding: 5,
          yPadding: 5,
          backgroundColor: chartParameters.TOOLTIP_COLOR,
          callbacks: {
            title: this.tooltipTitle.bind(this),
            label: this.tooltipLabel.bind(this),
            footer: this.tooltipFooter.bind(this)
          },
          borderColor: chartParameters.DARKCYAN,
          borderWidth: 3
        },
        scales: {
          gridLines: {
            color: chartParameters.GRID_COLOR,
            lineWidth: 1
          },
          xAxes: [
            {
              type: chartParameters.TIME,
              distribution: chartParameters.LINEAR,
              time: {
                unit: chartParameters.DAY,
                unitStepSize: 1,
                displayFormats: {
                  day: chartParameters.MM_DD_YY
                }
              },
              ticks: {
                source: chartParameters.AUTO,
                fontColor: chartParameters.WHITE,
                autoSkip: true,
                display: true,
                beginAtZero: true
              },
              gridLines: {
                display: true,
                color: chartParameters.GRID_COLOR,
                lineWidth: 1
              },
              scaleLabel: {
                display: true,
                labelString: chartParameters.DAYS,
                fontColor: chartParameters.WHITE,
                fontSize: 12,
                fontFamily: chartParameters.ARIAL
              }
            }
          ],
          yAxes: [
            {
              id: chartParameters.Y_AXIS,
              display: true,
              position: chartParameters.LEFT,
              ticks: {
                fontColor: chartParameters.WHITE,
                display: true,
                reverse: true,
                callback: value => {
                  return value + chartParameters.FT;
                }
              },
              gridLines: {
                display: true,
                color: chartParameters.GRID_COLOR,
                lineWidth: 1
              },
              scaleLabel: {
                display: true,
                labelString: chartParameters.DEPTH_LABEL,
                fontColor: chartParameters.WHITE,
                fontSize: 12,
                fontFamily: chartParameters.ARIAL
              }
            },
            {
              id: chartParameters.TCR,
              display: this.showTCR,
              position: chartParameters.RIGHT,
              ticks: {
                fontColor: chartParameters.WHITE,
                display: true,
                reverse: true,
                callback: value => {
                  return value + chartParameters.FT_DAY;
                }
              },
              scaleLabel: {
                display: true,
                labelString: chartParameters.TCR,
                fontColor: chartParameters.WHITE,
                fontSize: 12,
                fontFamily: chartParameters.ARIAL
              }
            }
          ]
        }
      }
    };
    return chartConfig;
  }
  selectdept() {
    this.showLoadBar = true;
    this.filteredDataSubscription = this.filteredDataService.currentdeptId.subscribe(
      filteredData => {
        if (filteredData.length >= 1) {
          this.filteredDataSubscription = this.filteredDataService.selectedStatus.subscribe(
            status => {
              this.projectDataSubscription = this.projectDataService
                .getFilterHeaderData(status)
                .valueChanges.subscribe(response => {
                  const initialdeptData = this.getdeptData(
                    response,
                    filteredData
                  );
                  const selecteddept = initialdeptData.find(dept => {
                    return dept.DeptName === this.selectedDeptName;
                  });
                  if (selecteddept) {
                    this.selectedDeptName = selecteddept.DeptName;
                    this.selectedDeptId = selecteddept.DeptId;
                    this.dept = new FormControl(this.selectedDeptName);
                    this.deptChartDataSubscription = this.deptChartDataService
                      .getdeptChartData(this.selectedDeptId)
                      .valueChanges.subscribe(deptChartData => {
                        if (deptChartData) {
                          this.buildChartResponse(deptChartData);
                        }
                        this.showLoadBar = false;
                      });
                  }
                });
            }
          );
        }
      }
    );
  }
  getdeptData(response, filteredData) {
    this.deptList = findUniqueProjects(response.data.projectList).map(
      list => list.dept
    );
    if (filteredData.length >= 1) {
      const alldeptData = this.deptList.map(dept =>
        dept.map(dept => {
          return dept;
        })
      );
      const alldept = [].concat.apply([], alldeptData);
      const filtereddept = alldept.filter(dept => {
        return filteredData.indexOf(dept.DeptId) >= 0;
      });
      this.deptList = filtereddept.map(dept => dept.DeptName);
      this.deptId = filtereddept.map(dept => dept.DeptId);
    } else {
      this.deptList = findUniqueProjects(response.data.projectList).map(
        list => list.dept
      );
      const initialdept = this.deptList.map(dept =>
        dept.map(dept => dept.DeptName)
      );
      const initialdeptId = this.deptList.map(dept =>
        dept.map(dept => dept.DeptId)
      );
      this.deptList = [].concat.apply([], initialdept);
      this.deptId = [].concat.apply([], initialdeptId);
    }
    const indexes = Array.from(this.deptList.keys());
    return this.builddeptData(indexes, this.deptList, this.deptId);
  }
  builddeptData(indexes, deptList, deptId) {
    return indexes.map(index => {
      return {
        DeptName: deptList[index],
        DeptId: deptId[index]
      };
    });
  }
  buildChartData(depthChartData) {
    return depthChartData.map(line => {
      return {
        x: line.date.split("T")[0],
        y: line.depth,
        TCR: line.TCR
      };
    });
  }
  buildChartTCRData(depthChartData) {
    return depthChartData.map(line => {
      return {
        x: line.date.split("T")[0],
        y: line.TCR,
        TCR: line.TCR
      };
    });
  }
  buildChartDataSet(label, data, color, dash) {
    if (label === chartParameters.TCR) {
      this.lineId = chartParameters.TCR;
    } else {
      this.lineId = chartParameters.Y_AXIS;
    }
    return {
      label: label,
      data: data,
      borderDash: dash,
      borderColor: color,
      pointBackgroundColor: color,
      pointBorderColor: color,
      fill: false,
      lineTension: 0,
      pointRadius: 0,
      yAxisID: this.lineId
    };
  }
  getChartDataSet(chartData) {
    const linesData = [
      this.buildChartDataSet(
        chartParameters.PLANNED,
        this.buildChartData(chartData["plannedChange"]),
        chartParameters.PLANNED_COLOR,
        [10, 5]
      ),
      this.buildChartDataSet(
        chartParameters.ACTUAL,
        this.buildChartData(chartData["actualChange"]),
        chartParameters.WHITE,
        []
      ),
      this.buildChartDataSet(
        chartParameters.TCR,
        this.buildChartTCRData(chartData["actualChange"]),
        COLORS_LINES[7],
        []
      )
    ];
    if (this.showTCR) {
      return linesData;
    } else {
      return linesData.slice(0, 2);
    }
  }
  buildChartResponse(response) {
    if (response && response.data && response.data.dept) {
      this.depthChartData = response.data["dept"];
      this.canvas = document.getElementById("depthChart");
      if (this.canvas != null) {
        this.context = this.canvas.getContext("2d");
      }
      if (this.depthChart) {
        this.depthChart.destroy();
      }
      this.depthChart = new Chart(
        this.context,
        this.createChartConfig(this.depthChartData)
      );
      this.createHighlightedLine();
    }
  }
  createHighlightedLine() {
    Chart.defaults.LineWithLine = Chart.defaults.line;
    Chart.controllers.LineWithLine = Chart.controllers.line.extend({
      draw: function(ease) {
        Chart.controllers.line.prototype.draw.call(this, ease);
        if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
          const activePoint = this.chart.tooltip._active[0],
            ctx = this.chart.ctx,
            x = activePoint.tooltipPosition().x,
            topY = this.chart.scales[chartParameters.Y_AXIS].top,
            bottomY = this.chart.scales[chartParameters.Y_AXIS].bottom;
          ctx.save();
          ctx.beginPath();
          ctx.moveTo(x, topY);
          ctx.lineTo(x, bottomY);
          ctx.lineWidth = 1;
          ctx.strokeStyle = chartParameters.STROKE_COLOR;
          ctx.stroke();
          ctx.restore();
        }
      }
    });
  }
  tooltipTitle() {
    return chartParameters.TOOLTIP_TITLE;
  }
  tooltipLabel(tooltipItem, data) {
    const date = tooltipItem.xLabel;
    const target = data.datasets[tooltipItem.datasetIndex].data.filter(
      point => {
        return point.x === date;
      }
    );
    this.TCR = Number(target[0].TCR);
    if (isNaN(this.TCR)) {
      return chartParameters.DASH + chartParameters.FT_HR;
    } else {
      return this.TCR.toFixed(1) + chartParameters.FT_HR;
    }
  }
  tooltipFooter(tooltipItem) {
    const date = moment(tooltipItem[0].xLabel.split("T")[0]).format(
      chartParameters.MM_DD_YY
    );
    return date;
  }
}

0 个答案:

没有答案