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;
}
}