You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've run into a problem with employing your financial chart module together with another canvas displaying a chart from chart.js.
The browser console points the "Uncaught TypeError: Class extends value undefined is not a constructor or null" error
to line 235 in chartjs-chart-financial.js:
class FinancialController extends Chart.BarController { ... }
Here are two templates being used in node red which are loaded into the front end. Both reference to individual canvasses with different IDs. (As you will see below, I try to destroy any previously existing chart instance)
First script:
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="../chartjs-chart-financial.js" type="text/javascript"></script>
<div style="width:1000px">
<canvas id="candleStickChart"></canvas>
</div>
<div>
Bar Type:
<select id="type">
<option value="candlestick" selected>Candlestick</option>
<option value="ohlc">OHLC</option>
</select>
Scale Type:
<select id="scale-type">
<option value="linear" selected>Linear</option>
<option value="logarithmic">Logarithmic</option>
</select>
Color Scheme:
<select id="color-scheme">
<option value="muted" selected>Muted</option>
<option value="neon">Neon</option>
</select>
Border:
<select id="border-color">
<option value="true" selected>Yes</option>
<option value="false">No</option>
</select>
<button id="update">Update</button>
<button id="randomizeData">Randomize Data</button>
</div>
<script>
(function(scope) {
var timer = setInterval(function() { //check that the luxon and other libs are loaded, if not wait
if (!window.luxon) return;
clearInterval(timer);
var barCount = 60;
var initialDateStr = '01 Apr 2017 00:00 Z';
debugger;
var ctx = document.getElementById('candleStickChart').getContext('2d');
ctx.canvas.width = 1000;
ctx.canvas.height = 250;
if (chart)
chart.destroy();
var chart = new Chart(ctx, {
type: 'candlestick',
data: {
datasets: [{
label: 'CHRT - Chart.js Corporation',
data: getRandomData(initialDateStr, barCount)
}]
}
});
var getRandomInt = function(max) {
return Math.floor(Math.random() * Math.floor(max));
};
function randomNumber(min, max) {
return Math.random() * (max - min) + min;
}
function randomBar(date, lastClose) {
var open = randomNumber(lastClose * 0.95, lastClose * 1.05).toFixed(2);
var close = randomNumber(open * 0.95, open * 1.05).toFixed(2);
var high = randomNumber(Math.max(open, close), Math.max(open, close) * 1.1).toFixed(2);
var low = randomNumber(Math.min(open, close) * 0.9, Math.min(open, close)).toFixed(2);
return {
t: date.valueOf(),
o: open,
h: high,
l: low,
c: close
};
}
function getRandomData(dateStr, count) {
var date = luxon.DateTime.fromRFC2822(dateStr);
var data = [randomBar(date, 30)];
while (data.length < count) {
date = date.plus({days: 1});
if (date.weekday <= 5) {
data.push(randomBar(date, data[data.length - 1].c));
}
}
return data;
}
var update = function() {
var dataset = chart.config.data.datasets[0];
// candlestick vs ohlc
var type = document.getElementById('type').value;
dataset.type = type;
// linear vs log
var scaleType = document.getElementById('scale-type').value;
chart.config.options.scales.y.type = scaleType;
// color
var colorScheme = document.getElementById('color-scheme').value;
if (colorScheme === 'neon') {
dataset.color = {
up: '#01ff01',
down: '#fe0000',
unchanged: '#999'
};
} else {
delete dataset.color;
}
var border = document.getElementById('border-color').value;
var defaultOpts = Chart.defaults.elements[type];
if (border === 'true') {
dataset.borderColor = defaultOpts.borderColor;
} else {
dataset.borderColor = {
up: defaultOpts.color.up,
down: defaultOpts.color.down,
unchanged: defaultOpts.color.up
};
}
chart.update();
};
document.getElementById('update').addEventListener('click', update);
document.getElementById('randomizeData').addEventListener('click', function() {
chart.data.datasets.forEach(function(dataset) {
dataset.data = getRandomData(initialDateStr, barCount);
});
update();
});
}, 100); // close out the setInterval
})(scope);
</script>
Second script:
<script>
//(function(scope) {
var ctx = document.getElementById("avgPriceChangesChart");
var numberOfSignals = '{{flow.selected_symbol_avgByNumberOfSignals}}';
var shortestPriceSeries = '{{flow.selected_symbol_shortestPriceSeries}}';
var omittedPriceSeries = '{{flow.selected_symbol_omittedPriceSeries}}';
var symbol = '{{flow.selected_symbol}}';
var demoData = {
labels: ["D1", "D2", "D3", "D4", "D5", "D6"],
datasets: [
{
label: "Signal 1",
backgroundColor: 'rgb(255, 99, 132)',
data: [0.2,-0.4,0.6,0.9,0.4,0.5]
},
{
label: "Signal 2",
backgroundColor: 'rgb(132, 99, 255)',
data: [-0.3,0.5,0.6,0.4,0.2,0.6]
},
{
label: "Signal 3",
backgroundColor: 'rgb(132, 255, 99)',
data: [0.1,-0.1,0.4,-0.2,0.4,0.8]
}
]
};
function createChart(someData) {
var avgPriceChangesChart = new Chart(ctx, {
type: "bar",
data: someData,
options: {
animation: {duration: 0},
title: {
responsive: true,
display: true,
text: "Averaged Price Changes (%) after " + numberOfSignals + " signals occurred in " + symbol
+ ".\nShortest price series: " + shortestPriceSeries + "\n"
+ ".\nOmitted price series (due to <20 price changes): " + omittedPriceSeries + "\n",
fontSize: 16,
fontColor: 'rgb(255,255,255)'
},
legend: {
display: true,
fontColor: 'white',
position: 'top'
},
maintainAspectRatio: false,
scales: {
xAxes: [{
barPercentage: 1.0,
barThickness: 6, // number (pixels) or 'flex'
maxBarThickness: 8, // number (pixels)
stacked: false,
gridLines: {
color: 'rgb(96,96,96)',
display: true
},
ticks: {
fontColor: 'white',
autoSkip: false
}
}],
yAxes: [{
stacked: false,
gridLines: {
color: 'rgb(96,96,96)',
display: true
},
ticks: {
beginAtZero: true,
fontColor: 'white',
min: -1,
max: 1
}//,
/*type: 'logarithmic'
afterBuildTicks: function (chartObj) { //Build ticks labelling as per your need
chartObj.ticks = [];
chartObj.ticks.push(0.01);
chartObj.ticks.push(0.1);
chartObj.ticks.push(1);
chartObj.ticks.push(10);
chartObj.ticks.push(100);
}//*/
}]
}
}
});
return avgPriceChangesChart;
}
/*if (avgPriceChangesChart !== undefined && Boolean(avgPriceChangesChart)) {
//alert("Trying to destroy old chart instance...");
debugger;
avgPriceChangesChart.destroy();
}*/
// for simplicity create a chart with simple demo data only. Nothing fancy.
avgPriceChangesChart = createChart(demoData); //msg.payload.data);
/*scope.$watch('msg', function(msg) {
if (msg) {
if (avgPriceChangesChart !== undefined && Boolean(avgPriceChangesChart)) {
//alert("Trying to destroy old chart instance...");
debugger;
avgPriceChangesChart.destroy();
}*/
/* debugger;
avgPriceChangesChart = createChart(msg.payload.data);
//avgPriceChangesChart.data.datasets[0].data[2] = 50; // Would update the first dataset's value of 'March' to be 50
//avgPriceChangesChart.data = msg.payload.data;
//avgPriceChangesChart["data"] = msg.payload.data;
avgPriceChangesChart.update();
}
});*/
//}) (scope);
</script>
The whole stack trace from the console looks as follows:
app.min.js:20 Uncaught TypeError: Class extends value undefined is not a constructor or null
at <anonymous>:238:41
at <anonymous>:14:76
at <anonymous>:15:2
at b (app.min.js:20)
at Function.globalEval (app.min.js:20)
at Object.dataFilter (app.min.js:20)
at app.min.js:20
at l (app.min.js:20)
at XMLHttpRequest.<anonymous> (app.min.js:20)
at Object.send (app.min.js:20)
....
VM2648 chart.js:5161 Uncaught Error: "candlestick" is not a registered controller.
at Registry._get (VM2648 chart.js:5161)
at Registry.getController (VM2648 chart.js:5106)
at Chart.buildOrUpdateControllers (VM2648 chart.js:6188)
at Chart.update (VM2648 chart.js:6227)
at new Chart (VM2648 chart.js:5988)
at <anonymous>:20:21
_get @ VM2648 chart.js:5161
getController @ VM2648 chart.js:5106
buildOrUpdateControllers @ VM2648 chart.js:6188
update @ VM2648 chart.js:6227
Chart @ VM2648 chart.js:5988
(anonymous)
VM2648 chart.js:5945 Uncaught Error: Canvas is already in use. Chart with ID '0' must be destroyed before the canvas can be reused.
at new Chart (VM2648 chart.js:5945)
at <anonymous>:20:21
Chart @ VM2648 chart.js:5945
(anonymous)
VM2648 chart.js:5161 Uncaught Error: "candlestick" is not a registered controller.
at Registry._get (VM2648 chart.js:5161)
at Registry.getController (VM2648 chart.js:5106)
at Chart.buildOrUpdateControllers (VM2648 chart.js:6188)
at Chart.update (VM2648 chart.js:6227)
at Chart._resize (VM2648 chart.js:6053)
at Chart.resize (VM2648 chart.js:6027)
at listener (VM2648 chart.js:6509)
at VM2648 chart.js:1776
at VM2648 chart.js:34
I would be very much appreciate any hints to what I'm doing wrong.
Cheers,
Marcel
The text was updated successfully, but these errors were encountered:
CreativeWarlock
changed the title
Uncaught TypeError: Class extends value undefined is not a constructor or null
Using classic chart from Chart.js and a financial chart: Uncaught TypeError: Class extends value undefined is not a constructor or null
Feb 27, 2021
Hi mate,
I've run into a problem with employing your financial chart module together with another canvas displaying a chart from chart.js.
The browser console points the "Uncaught TypeError: Class extends value undefined is not a constructor or null" error
to line 235 in chartjs-chart-financial.js:
class FinancialController extends Chart.BarController { ... }
Here are two templates being used in node red which are loaded into the front end. Both reference to individual canvasses with different IDs. (As you will see below, I try to destroy any previously existing chart instance)
First script:
Second script:
The whole stack trace from the console looks as follows:
I would be very much appreciate any hints to what I'm doing wrong.
Cheers,
Marcel
The text was updated successfully, but these errors were encountered: