Prior to eCharts being adopted as the charting tool for Dashboard 2, I had created all my charts using the ui-template node in DB2. I'm trying to figure out a couple of things:
-
Do I still need to include the source CDN (e.g. <script type="text/javascript" src="https://fastly.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>) in my ui-template or is there an easier/more efficient way to do it?
-
One of the reasons for using eCharts (or Chart.js) was that the built in charting options had limited configuration/customization capability. With the ability to now set these via msg.ui_update would it make sense to use the built in charts vs ui-template? Below is an example of ui-template that I am currently using:
<template>
<div ref="charttpw15" style="width: 100%; height: 100%"></div>
<style>
/* This rule targets the ECharts tooltip container and forces its styles */
.echarts-tooltip-dark {
background-color: #1C1C1C !important;
color: #fff !important;
}
.echarts-tooltip-light {
background-color: #1C1C1C !important;
color: #fff !important;
}
</style>
</template>
<script type="text/javascript" src="https://fastly.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
<script>
export default {
data() {
return {
myChart: null,
resizeHandler: null,
};
},
watch: {
msg: function () {
if (this.msg && this.msg.topic === "data" && this.myChart && this.msg.payload) {
const p = this.msg.payload;
this.update(p.labels, p, this.msg.title, this.msg.colors, this.msg.legend);
}
}
},
mounted() {
this.$nextTick(() => {
const ready = setInterval(() => {
const container = this.$refs.charttpw15;
if (window.echarts && container && container.offsetWidth > 0 && container.offsetHeight > 0) {
clearInterval(ready);
this.init();
// If data already exists at mount, draw immediately
if (this.msg && this.msg.topic === "data" && this.msg.payload) {
const p = this.msg.payload;
this.update(p.labels, p, this.msg.title, this.msg.colors, this.msg.legend);
}
// Setup resize listener
this.resizeHandler = () => { if (this.myChart) this.myChart.resize(); };
window.addEventListener('resize', this.resizeHandler);
// Optional: force resize after layout settles
setTimeout(() => { if (this.myChart) this.myChart.resize(); }, 300);
}
}, 100);
});
},
unmounted() { // <-- correct for Dashboard 2
if (this.myChart) {
this.myChart.dispose();
}
if (this.resizeHandler) {
window.removeEventListener('resize', this.resizeHandler);
}
},
methods: {
init() {
this.myChart = echarts.init(this.$refs.charttpw15, "dark");
this.myChart.setOption({
title: { text: "Waiting for data..." },
textStyle: { fontFamily: 'Tahoma,sans-serif' },
series: []
});
},
update(xAxisData, datasets, title, colors, legendData) {
this.myChart.setOption({
textStyle: { fontFamily: 'Tahoma,sans-serif' },
title: { text: title,
left:'auto',
textStyle:{
fontWeight:'normal',
fontSize: 22,
},
},
tooltip: {
trigger: 'item',
/*---Disabled options for tooltip---
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985' // Optional: style the axis pointer label itself
}
},
backgroundColor: 'rgba(0,0,0,0.8)', // Semi-transparent black background
textStyle: {
color: '#fff' // White text
},
formatter: function (params) {
console.log('Tooltip params:', params);
let tooltipContent = '';
params.forEach(function (item) {
if (item.seriesName) {
tooltipContent += `${item.seriesName}: ${item.data ?? 'n/a'}<br>`;
}
});
return tooltipContent;
}
*/
},
legend: {
show: true,
data: legendData || [
{ name: 'Home', icon: 'rect' },
{ name: 'Solar', icon: 'rect' },
{ name: 'Grid', icon: 'rect' },
{ name: 'Battery', icon: 'rect' }
],
textStyle: { fontSize: 16, fontWeight: 'bold' }
},
toolbox: { show: false },
grid: { left: "3%", right: "4%", containLabel: true },
xAxis: {
type: "category",
boundaryGap: false,
data: xAxisData,
name: 'Time',
nameGap: 30,
nameLocation: 'middle',
nameTextStyle: { fontWeight: 'bold', fontSize: 16 },
axisTick: { show: true },
axisLabel: { formatter: "{value}", color: 'white' },
axisLine: { lineStyle: { color: 'white', width: 2 } },
onZero: false
},
yAxis: {
type: "value",
name: 'kWh',
nameGap: 50,
nameLocation: 'middle',
nameTextStyle: { fontWeight: 'bold', fontSize: 16 },
axisLine: { show: true, lineStyle: { color: 'white', width: 2 } },
axisTick: { show: true },
axisLabel: { formatter: "{value} kWh", color: 'white' },
splitLine: { show: true, lineStyle: { color: '#333' } },
nameTextStyle: { fontSize: 16, fontWeight: 'bold' },
axisPointer: { snap: true },
scale: true,
},
series: [
{
name: 'Home',
type: 'line',
smooth: true,
connectNulls: true,
data: datasets.home || [],
lineStyle: { color: colors.home, width: 3, type: 'solid' },
showSymbol: false,
},
{
name: 'Solar',
type: 'bar',
connectNulls: true,
data: datasets.solar || [],
barMaxWidth: 40,
itemStyle: { color: colors.solar, borderColor: colors.solar, borderWidth: 1 },
stack: 'day'
},
{
name: 'Grid',
type: 'bar',
connectNulls: true,
data: datasets.grid || [],
barMaxWidth: 40,
itemStyle: { color: colors.grid, borderColor: colors.grid, borderWidth: 1 },
stack: 'day'
},
{
name: 'Battery',
type: 'bar',
connectNulls: true,
data: datasets.battery || [],
barMaxWidth: 40,
itemStyle: { color: colors.battery, borderColor: colors.battery, borderWidth: 1 },
stack: 'day'
}
]
});
}
}
}
</script>
Thanks for your help.