Problem with Template UI element / TypeError: Class extends value undefined is not a function or null / 2 Canvases

Hi guys,

has anyone ever run into this exception shown on a Browser console?
TypeError: Class extends value undefined is not a function or null
(javascript - TypeError: Class extends value undefined is not a function or null - Stack Overflow)

I've been trying to reliably display a candle stick chart on my dashboard. On my very first deploys the page loaded and displayed the chart properly. At some point it stopped working / for some reason, when I reload the page the chart is no more displayed and the above exception is thrown on the console.

The flow looks like this:


Here's the code from the selected nodes as shown above:

[{"id":"80001d10.90e61","type":"ui_template","z":"9ba23ed4.19e7f","g":"d2cdd39e.32eff","group":"5a4200da.62c9e","name":"Template Display CandleStick Chart","order":19,"width":"36","height":"14","format":"<center>\n    <H3>Candlestick Chart needs reloading.</H3>\n</center>","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":false,"templateScope":"local","x":640,"y":1160,"wires":[[]]},{"id":"7f1c8b09.7b4854","type":"ui_template","z":"9ba23ed4.19e7f","d":true,"g":"d2cdd39e.32eff","group":"5a4200da.62c9e","name":"Load JS libs","order":12,"width":0,"height":0,"format":"<script src=\"https://cdn.jsdelivr.net/npm/luxon@1.24.1\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/chart.js@3.0.0-beta.9/dist/chart.js\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@0.2.1\"></script>\n<script src=\"../chartjs-chart-financial.js\" type=\"text/javascript\"></script>","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":false,"templateScope":"local","x":570,"y":1120,"wires":[[]]},{"id":"80a913cd.0158a","type":"template","z":"9ba23ed4.19e7f","g":"d2cdd39e.32eff","name":"CandleStick Chart","field":"template","fieldType":"msg","format":"javascript","syntax":"mustache","template":"<script src=\"https://cdn.jsdelivr.net/npm/luxon@1.24.1\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/chart.js@3.0.0-beta.9/dist/chart.js\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@0.2.1\"></script>\n<script src=\"../chartjs-chart-financial.js\" type=\"text/javascript\"></script>\n\n<h1>Sample Candlestick Chart</h1>\n<!--p>See the <a href=\"https://github.com/chartjs/chartjs-chart-financial/tree/master/docs\">source for this example</a>, <a href=\"https://github.com/chartjs/chartjs-chart-financial\">README</a>, and <a href=\"https://www.chartjs.org/docs/\">Chart.js docs</a> for more details.</p-->\n\n<div style=\"width:1000px\">\n\t<canvas id=\"candleStickChart\"></canvas>\n</div>\n\n<div>\n\tBar Type:\n\t<select id=\"type\">\n\t\t<option value=\"candlestick\" selected>Candlestick</option>\n\t\t<option value=\"ohlc\">OHLC</option>\n\t</select>\n\tScale Type:\n\t<select id=\"scale-type\">\n\t\t<option value=\"linear\" selected>Linear</option>\n\t\t<option value=\"logarithmic\">Logarithmic</option>\n\t</select>\n\tColor Scheme:\n\t<select id=\"color-scheme\">\n\t\t<option value=\"muted\" selected>Muted</option>\n\t\t<option value=\"neon\">Neon</option>\n\t</select>\n\tBorder:\n\t<select id=\"border-color\">\n\t\t<option value=\"true\" selected>Yes</option>\n\t\t<option value=\"false\">No</option>\n\t</select>\n\t<button id=\"update\">Update</button>\n\t<button id=\"randomizeData\">Randomize Data</button>\n</div>\n\n<script>//*/\nvar barCount = 60;\nvar initialDateStr = '01 Apr 2017 00:00 Z';\n\nvar ctx = document.getElementById('candleStickChart').getContext('2d');\nctx.canvas.width = 1000;\nctx.canvas.height = 250;\n\n//if (chart)\n    //chart.destroy();\n\nvar chart = new Chart(ctx, {\n\ttype: 'candlestick',\n\tdata: {\n\t\tdatasets: [{\n\t\t\tlabel: 'CHRT - Chart.js Corporation',\n\t\t\tdata: getRandomData(initialDateStr, barCount)\n\t\t}]\n\t}\n});\n\nvar getRandomInt = function(max) {\n\treturn Math.floor(Math.random() * Math.floor(max));\n};\n\nfunction randomNumber(min, max) {\n\treturn Math.random() * (max - min) + min;\n}\n\nfunction randomBar(date, lastClose) {\n\tvar open = randomNumber(lastClose * 0.95, lastClose * 1.05).toFixed(2);\n\tvar close = randomNumber(open * 0.95, open * 1.05).toFixed(2);\n\tvar high = randomNumber(Math.max(open, close), Math.max(open, close) * 1.1).toFixed(2);\n\tvar low = randomNumber(Math.min(open, close) * 0.9, Math.min(open, close)).toFixed(2);\n\treturn {\n\t\tt: date.valueOf(),\n\t\to: open,\n\t\th: high,\n\t\tl: low,\n\t\tc: close\n\t};\n\n}\n\nfunction getRandomData(dateStr, count) {\n\tvar date = luxon.DateTime.fromRFC2822(dateStr);\n\tvar data = [randomBar(date, 30)];\n\twhile (data.length < count) {\n\t\tdate = date.plus({days: 1});\n\t\tif (date.weekday <= 5) {\n\t\t\tdata.push(randomBar(date, data[data.length - 1].c));\n\t\t}\n\t}\n\treturn data;\n}\n\nvar update = function() {\n\tvar dataset = chart.config.data.datasets[0];\n\n\t// candlestick vs ohlc\n\tvar type = document.getElementById('type').value;\n\tdataset.type = type;\n\n\t// linear vs log\n\tvar scaleType = document.getElementById('scale-type').value;\n\tchart.config.options.scales.y.type = scaleType;\n\n\t// color\n\tvar colorScheme = document.getElementById('color-scheme').value;\n\tif (colorScheme === 'neon') {\n\t\tdataset.color = {\n\t\t\tup: '#01ff01',\n\t\t\tdown: '#fe0000',\n\t\t\tunchanged: '#999'\n\t\t};\n\t} else {\n\t\tdelete dataset.color;\n\t}\n\n\tvar border = document.getElementById('border-color').value;\n\tvar defaultOpts = Chart.defaults.elements[type];\n\tif (border === 'true') {\n\t\tdataset.borderColor = defaultOpts.borderColor;\n\t} else {\n\t\tdataset.borderColor = {\n\t\t\tup: defaultOpts.color.up,\n\t\t\tdown: defaultOpts.color.down,\n\t\t\tunchanged: defaultOpts.color.up\n\t\t};\n\t}\n\n\tchart.update();\n};\n\ndocument.getElementById('update').addEventListener('click', update);\n\ndocument.getElementById('randomizeData').addEventListener('click', function() {\n\tchart.data.datasets.forEach(function(dataset) {\n\t\tdataset.data = getRandomData(initialDateStr, barCount);\n\t});\n\tupdate();\n});\n</script>","output":"str","x":370,"y":1160,"wires":[["80001d10.90e61","7f1c8b09.7b4854"]]},{"id":"176dfef5.4056c1","type":"ui_button","z":"9ba23ed4.19e7f","g":"d2cdd39e.32eff","name":"Load CandleSticks","group":"5a4200da.62c9e","order":18,"width":"5","height":1,"passthru":false,"label":"Load CandleSticks Chart","tooltip":"Loads the candle sticks chart","color":"","bgcolor":"","icon":"refresh","payload":"0","payloadType":"num","topic":"","topicType":"str","x":170,"y":1160,"wires":[["80a913cd.0158a"]]},{"id":"312bf216.43527e","type":"hidden-ui-load","z":"9ba23ed4.19e7f","g":"d2cdd39e.32eff","group":"3335b9df.9253a6","order":0,"name":"Load Page","x":140,"y":1120,"wires":[["7531d000.a298f","40f182b3.5c4d9c","bb299be3.5853e8","80a913cd.0158a"]]},{"id":"5a4200da.62c9e","type":"ui_group","name":"Symbol Analysis","tab":"a9b97a36.b1b538","order":2,"disp":true,"width":"36","collapse":false},{"id":"3335b9df.9253a6","type":"ui_group","name":"Table_w_Signals","tab":"5fd14a8a.e8efa4","order":2,"disp":false,"width":"30","collapse":false},{"id":"a9b97a36.b1b538","type":"ui_tab","name":"Charts","icon":"poll","order":5,"disabled":false,"hidden":false},{"id":"5fd14a8a.e8efa4","type":"ui_tab","name":"Signals","icon":"add_alert","order":1,"disabled":false,"hidden":false}]

The HTML + JS code from within that 'CandleStick Chart' template looks as follows:

<script src="https://cdn.jsdelivr.net/npm/luxon@1.24.1"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.0.0-beta.9/dist/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@0.2.1"></script>
<script src="../chartjs-chart-financial.js" type="text/javascript"></script>

<h1>Sample Candlestick Chart</h1>
<!--p>See the <a href="https://github.com/chartjs/chartjs-chart-financial/tree/master/docs">source for this example</a>, <a href="https://github.com/chartjs/chartjs-chart-financial">README</a>, and <a href="https://www.chartjs.org/docs/">Chart.js docs</a> for more details.</p-->

<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>//*/
var barCount = 60;
var initialDateStr = '01 Apr 2017 00:00 Z';

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();
});
</script>

According to this thread on StackOverflow javascript - TypeError: Class extends value undefined is not a function or null - Stack Overflow the exception is triggered on a circularly importing, so I wonder how the heck is that happening?

Am I missing an important "feature" of the template UI element? It seems to be cashing stuff?
Also there're a few options in that template UI available. About the last option "Reload last value on refresh" I'm not sure if it helps or harms:

image

Why is the exception thrown on a page refresh of the UI dashboard? Should it not clear the cache and start with a fresh new slate?

On a side note, there's another bugger, which drives me crazy. I had a line chart on the dashboard which I disabled for now. The error with that - which I was trying to fix (before this Exception popped up) was a conflict with 2 canvases interfering with one another. I can't recall that exception again, but since the 2nd candlestick dashboard is not loading at all anymore, I stopped trying to fix this problem (A solution seems to be posted on SO javascript - Destroy chart.js bar graph to redraw other graph in same <canvas> - Stack Overflow).

As you can see, I also have a currently disabled 'Load JS Libs' template node which would (if enabled) place the JS includes at the start of the page. Not sure if this is the correct approach of if including the JS libraries in the template script is OK (as shown in the lengthy JS script for the candle sticks chart above).

Sorry for presenting you a problem while everything is still work in progress (with the intermingled "canvas with 2 charts" problem).
Maybe someone might share some experience and point me to what I'm probably doing wrong?

Best regards,
Marcel