How to configure Echarts in Dashboard 2?

I have been using Echarts in D1 for a couple of years and it works great. Here is a D1 example of a line chart displaying static data with a UI-template node.

[
    {
        "id": "fe0c5554b14b7f8f",
        "type": "ui_template",
        "z": "fdab7f193d01934c",
        "group": "d6a11160367b3bdb",
        "name": "Tons per hour",
        "order": 4,
        "width": "10",
        "height": "4",
        "format": "<!DOCTYPE html>\n<html lang=\"en\" style=\"height: 100%\">\n\n<head>\n    <meta charset=\"utf-8\">\n</head>\n\n<body style=\"height: 100%; margin: 0\">\n\n    <div id=\"charttpw\" style=\"width: 500px; height: 200px;\"></div>\n\n\n    <script type=\"text/javascript\" src=\"https://fastly.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js\"></script>\n\n\n\n\n    <script>\n        (function(scope) {\n    var timer = setInterval(function() {\n    if (!window.echarts) return;\n    clearInterval(timer);\n     \n    var myData;\n     \n    //var chart5 = document.getElementById('chart5');\n    var myChart = echarts.init(document.getElementById('charttpw'), 'dark');\n    //var myChart = echarts.init(chart5);\n    myChart.setOption({\n    title: {\n    text: 'Tons per Hour',\n    //subtext: 'Fake Data'\n    },\n    tooltip: {\n    trigger: 'axis',\n    axisPointer: {\n    type: 'cross'\n    }\n    },\n    toolbox: {\n    show: true,\n    feature: {\n    saveAsImage: {}\n    }\n    },\n    grid: {\n    left: '3%',\n    right: '4%',\n    //top: '30%',\n    containLabel: true\n    },\n    xAxis: {\n    type: 'category',\n    boundaryGap: false,\n    // prettier-ignore\n/*    data: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00', '09:00', '10:00', '11:00',\n    '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00','22:00','23:00']\n    }, */\n    data: ['07:00', '08:00', '09:00', '10:00', '11:00',\n    '12:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00']\n    },\n    yAxis: {\n    type: 'value',\n    axisLabel: {\n    formatter: '{value} T'\n    },\n    axisPointer: {\n    snap: true\n    }\n    },\n    visualMap: {\n    show: false,\n    dimension: 0,\n    pieces: [{\"lte\":9,\"color\":\"green\"},{\"gt\":9,\"lte\":11,\"color\":\"red\"},{\"gt\":11,\"color\":\"green\"}]\n    },\n    series: [\n    {\n    name: 'Tons',\n    type: 'line',\n    smooth: true,\n    // prettier-ignore\n    data: [5300, 9280, 11250, 1260, 2270, 4300, 5550, 2500, 2400, 4390, 9380, 12390, 10400, 11500, 7600, 8750, 4800, 8700, 9600, 4400, 6600, 6750, 8980, 7000],\n    markArea: {\n    itemStyle: {\n    color: 'rgba(255, 173, 177, 0.4)'\n    },\n   data: [\n    [{\"name\":\"Max Peak\",\"xAxis\":\"9:00\"},{\"xAxis\":\"11:00\"}]\n    ] \n    }\n    }\n    ]\n    });\n\n \n    scope.$watch('msg', function (msg) { //watch for an incoming NR msg\n     if (msg) {\n        //myData = msg;\n        myChart.setOption({\n        title: {\n        text: 'Tons per Hour',\n        subtext: 'weekly avg'\n        },\n        legend: {right:25},\n        tooltip: {\n        trigger: 'axis',\n        axisPointer: {\n        type: 'cross'\n        }\n        },\n        toolbox: {\n        show: true,\n        feature: {\n        saveAsImage: {}\n        }\n        },\n        grid: {\n        left: '3%',\n        right: '4%',\n        bottom: '5%',\n        //top: '5%',\n        containLabel: true\n        },\n        xAxis: {\n        type: 'category',\n        axisLabel: {\n        interval:0\n        //rotate:45\n        },\n        boundaryGap: false,\n        // prettier-ignore\n      /*  data: ['07:00', '08:00', '09:00', '10:00', '11:00',\n        '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00'] */\n        data: ['07:00', '08:00', '09:00', '10:00', '11:00',\n        '12:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00']\n        },\n        yAxis: {\n        type: 'value',\n        axisLabel: {\n        formatter: '{value} T'\n        },\n        axisPointer: {\n        snap: true\n        }\n        },\n        visualMap: {\n        show: false,\n        dimension: 0,\n        pieces: msg.pieces\n        },\n        series: [\n            {\n            name: 'avg',\n            type: 'bar',\n            itemStyle: {\n            //color: 'rgba(190, 190, 190, 0.4)',\n            opacity: 0.4\n            }, \n            tooltip: {\n            valueFormatter: function (value) {\n            return value + ' T';\n            }\n            },\n            data: msg.tons_pw,\n            color:['#ace'],\n           // color:['#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE'],\n            //[6945,4967,7994,4510,8395,5413,8662,7703,7826,8099,8135,6557],\n            barWidth: '85%'\n            \n            }, \n            \n        {\n        name: 'Tons',\n        type: 'line',\n        smooth: true,\n        // prettier-ignore\n        data: msg.tons,\n        color: ['green'],\n        markArea: {\n        itemStyle: {\n        color: 'rgba(255, 173, 177, 0.4)'\n        },\n        data: [msg.mark]\n        } \n        } \n        ]\n        });\n        \n        };\n        });\n        }, 1000);\n        })(scope);\n\n    </script>\n</body>\n\n</html>",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 280,
        "y": 160,
        "wires": [
            []
        ]
    },
    {
        "id": "d6a11160367b3bdb",
        "type": "ui_group",
        "name": "Group 2",
        "tab": "db7e79aa7cb36dc9",
        "order": 2,
        "disp": false,
        "width": "30",
        "collapse": false,
        "className": ""
    },
    {
        "id": "db7e79aa7cb36dc9",
        "type": "ui_tab",
        "name": "Analytics2",
        "icon": "fa-line-chart fa-lg",
        "order": 1,
        "disabled": false,
        "hidden": false
    }
]

I tried doing a similar thing with the D2 ui-template node. I have followed the instructions for pure html/javascript/css in the documentation but can't get it to work. Below is one of the configurations I have tried.

[
    {
        "id": "6a963405aac53b95",
        "type": "ui-template",
        "z": "7f61078bebd11819",
        "group": "b0dad8343feda1c6",
        "page": "",
        "ui": "",
        "name": "",
        "order": 4,
        "width": "0",
        "height": "0",
        "head": "",
        "format": "<template>\n<!DOCTYPE html>\n<html lang=\"en\" style=\"height: 100%\">\n\n<head>\n    <meta charset=\"utf-8\">\n</head>\n\n<body style=\"height: 100%; margin: 0\">\n\n    <div id=\"charttpw\" style=\"width: 500px; height: 200px;\"></div>\n\n</body>\n\n</html>\n</template>\n\n<script type=\"text/javascript\" src=\"https://fastly.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js\"></script>\n\n\n\n\n<script>\n    (function(scope) {\n    var timer = setInterval(function() {\n    if (!window.echarts) return;\n    clearInterval(timer);\n     \n    var myData;\n     \n    //var chart5 = document.getElementById('chart5');\n    var myChart = echarts.init(document.getElementById('charttpw'), 'dark');\n    //var myChart = echarts.init(chart5);\n    myChart.setOption({\n    title: {\n    text: 'Tons per Hour',\n    //subtext: 'Fake Data'\n    },\n    tooltip: {\n    trigger: 'axis',\n    axisPointer: {\n    type: 'cross'\n    }\n    },\n    toolbox: {\n    show: true,\n    feature: {\n    saveAsImage: {}\n    }\n    },\n    grid: {\n    left: '3%',\n    right: '4%',\n    //top: '30%',\n    containLabel: true\n    },\n    xAxis: {\n    type: 'category',\n    boundaryGap: false,\n    // prettier-ignore\n/*    data: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00', '09:00', '10:00', '11:00',\n    '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00','22:00','23:00']\n    }, */\n    data: ['07:00', '08:00', '09:00', '10:00', '11:00',\n    '12:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00']\n    },\n    yAxis: {\n    type: 'value',\n    axisLabel: {\n    formatter: '{value} T'\n    },\n    axisPointer: {\n    snap: true\n    }\n    },\n    visualMap: {\n    show: false,\n    dimension: 0,\n    pieces: [{\"lte\":9,\"color\":\"green\"},{\"gt\":9,\"lte\":11,\"color\":\"red\"},{\"gt\":11,\"color\":\"green\"}]\n    },\n    series: [\n    {\n    name: 'Tons',\n    type: 'line',\n    smooth: true,\n    // prettier-ignore\n    data: [5300, 9280, 11250, 1260, 2270, 4300, 5550, 2500, 2400, 4390, 9380, 12390, 10400, 11500, 7600, 8750, 4800, 8700, 9600, 4400, 6600, 6750, 8980, 7000],\n    markArea: {\n    itemStyle: {\n    color: 'rgba(255, 173, 177, 0.4)'\n    },\n   data: [\n    [{\"name\":\"Max Peak\",\"xAxis\":\"9:00\"},{\"xAxis\":\"11:00\"}]\n    ] \n    }\n    }\n    ]\n    });\n\n \n    scope.$watch('msg', function (msg) { //watch for an incoming NR msg\n     if (msg) {\n        //myData = msg;\n        myChart.setOption({\n        title: {\n        text: 'Tons per Hour',\n        subtext: 'weekly avg'\n        },\n        legend: {right:25},\n        tooltip: {\n        trigger: 'axis',\n        axisPointer: {\n        type: 'cross'\n        }\n        },\n        toolbox: {\n        show: true,\n        feature: {\n        saveAsImage: {}\n        }\n        },\n        grid: {\n        left: '3%',\n        right: '4%',\n        bottom: '5%',\n        //top: '5%',\n        containLabel: true\n        },\n        xAxis: {\n        type: 'category',\n        axisLabel: {\n        interval:0\n        //rotate:45\n        },\n        boundaryGap: false,\n        // prettier-ignore\n      /*  data: ['07:00', '08:00', '09:00', '10:00', '11:00',\n        '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00'] */\n        data: ['07:00', '08:00', '09:00', '10:00', '11:00',\n        '12:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00']\n        },\n        yAxis: {\n        type: 'value',\n        axisLabel: {\n        formatter: '{value} T'\n        },\n        axisPointer: {\n        snap: true\n        }\n        },\n        visualMap: {\n        show: false,\n        dimension: 0,\n        pieces: msg.pieces\n        },\n        series: [\n            {\n            name: 'avg',\n            type: 'bar',\n            itemStyle: {\n            //color: 'rgba(190, 190, 190, 0.4)',\n            opacity: 0.4\n            }, \n            tooltip: {\n            valueFormatter: function (value) {\n            return value + ' T';\n            }\n            },\n            data: msg.tons_pw,\n            color:['#ace'],\n           // color:['#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE'],\n            //[6945,4967,7994,4510,8395,5413,8662,7703,7826,8099,8135,6557],\n            barWidth: '85%'\n            \n            }, \n            \n        {\n        name: 'Tons',\n        type: 'line',\n        smooth: true,\n        // prettier-ignore\n        data: msg.tons,\n        color: ['green'],\n        markArea: {\n        itemStyle: {\n        color: 'rgba(255, 173, 177, 0.4)'\n        },\n        data: [msg.mark]\n        } \n        } \n        ]\n        });\n        \n        };\n        });\n        }, 1000);\n        })(scope);\n\n</script>",
        "storeOutMessages": true,
        "passthru": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 600,
        "y": 160,
        "wires": [
            []
        ]
    },
    {
        "id": "b0dad8343feda1c6",
        "type": "ui-group",
        "name": "Input",
        "page": "0405dc4a843d1793",
        "width": "12",
        "height": "1",
        "order": -1,
        "showTitle": true,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "0405dc4a843d1793",
        "type": "ui-page",
        "name": "Report Builder",
        "ui": "f5c9bde1e67f59d3",
        "path": "/page1",
        "icon": "home",
        "layout": "grid",
        "theme": "ba2e667d0985ce12",
        "order": -1,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "f5c9bde1e67f59d3",
        "type": "ui-base",
        "name": "Reports",
        "path": "/dashboard",
        "includeClientData": true,
        "acceptsClientConfig": [
            "ui-notification",
            "ui-control"
        ],
        "showPathInSidebar": false,
        "navigationStyle": "icon"
    },
    {
        "id": "ba2e667d0985ce12",
        "type": "ui-theme",
        "name": "Default Theme",
        "colors": {
            "surface": "#ffffff",
            "primary": "#0094CE",
            "bgPage": "#eeeeee",
            "groupBg": "#ffffff",
            "groupOutline": "#cccccc"
        },
        "sizes": {
            "pagePadding": "12px",
            "groupGap": "12px",
            "groupBorderRadius": "4px",
            "widgetGap": "12px"
        }
    }
]

If anyone knows how to make this work in D2 please let me know. Thanks!

The syntax is a little different in Dashboard 2 because the developers have moved away from the older Angular Front-end library to Vue.

You can read in more detail how to listen to a msg in the D2 docs : Example (Raw JavaScript)

// Subscribe to the incoming msg's
    this.$socket.on('msg-input:' + this.id, function(msg) {
        // do stuff with the message
        alert('message received: ' + msg.payload)
    })

Test Flow (not fully tested since i havent used echarts before, but at least its something to get you started) :

[{"id":"6a963405aac53b95","type":"ui-template","z":"54efb553244c241f","group":"b0dad8343feda1c6","page":"","ui":"","name":"","order":4,"width":"0","height":"0","head":"","format":"<template>\n  <div id=\"charttpw\" style=\"width: 500px; height: 200px\"></div>\n</template>\n\n<script type=\"text/javascript\" src=\"https://fastly.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js\"></script>\n\n<script>\n\nfunction init () {\n    console.log('echarts loaded')\n\n var myData;\n\n  //var chart5 = document.getElementById('chart5');\n  var myChart = echarts.init(document.getElementById(\"charttpw\"), \"dark\");\n  //var myChart = echarts.init(chart5);\n  myChart.setOption({\n    title: {\n      text: \"Tons per Hour\",\n      //subtext: 'Fake Data'\n    },\n    tooltip: {\n      trigger: \"axis\",\n      axisPointer: {\n        type: \"cross\",\n      },\n    },\n    toolbox: {\n      show: true,\n      feature: {\n        saveAsImage: {},\n      },\n    },\n    grid: {\n      left: \"3%\",\n      right: \"4%\",\n      //top: '30%',\n      containLabel: true,\n    },\n    xAxis: {\n      type: \"category\",\n      boundaryGap: false,\n      // prettier-ignore\n      /*    data: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00', '09:00', '10:00', '11:00',\n'12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00','22:00','23:00']\n}, */\n      data: ['07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00'],\n    },\n    yAxis: {\n      type: \"value\",\n      axisLabel: {\n        formatter: \"{value} T\",\n      },\n      axisPointer: {\n        snap: true,\n      },\n    },\n    visualMap: {\n      show: false,\n      dimension: 0,\n      pieces: [\n        { lte: 9, color: \"green\" },\n        { gt: 9, lte: 11, color: \"red\" },\n        { gt: 11, color: \"green\" },\n      ],\n    },\n    series: [\n      {\n        name: \"Tons\",\n        type: \"line\",\n        smooth: true,\n        // prettier-ignore\n        data: [5300, 9280, 11250, 1260, 2270, 4300, 5550, 2500, 2400, 4390, 9380, 12390, 10400, 11500, 7600, 8750, 4800, 8700, 9600, 4400, 6600, 6750, 8980, 7000],\n        markArea: {\n          itemStyle: {\n            color: \"rgba(255, 173, 177, 0.4)\",\n          },\n          data: [[{ name: \"Max Peak\", xAxis: \"9:00\" }, { xAxis: \"11:00\" }]],\n        },\n      },\n    ],\n  });\n\n  // Subscribe to the incoming msg's\n  this.$socket.on(\"msg-input:\" + this.id, function (msg) {\n    // do stuff with the message\n    if (msg) {\n      //myData = msg;\n      myChart.setOption({\n        title: {\n          text: \"Tons per Hour\",\n          subtext: \"weekly avg\",\n        },\n        legend: { right: 25 },\n        tooltip: {\n          trigger: \"axis\",\n          axisPointer: {\n            type: \"cross\",\n          },\n        },\n        toolbox: {\n          show: true,\n          feature: {\n            saveAsImage: {},\n          },\n        },\n        grid: {\n          left: \"3%\",\n          right: \"4%\",\n          bottom: \"5%\",\n          //top: '5%',\n          containLabel: true,\n        },\n        xAxis: {\n          type: \"category\",\n          axisLabel: {\n            interval: 0,\n            //rotate:45\n          },\n          boundaryGap: false,\n          // prettier-ignore\n          /*  data: ['07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00'] */\n          data: ['07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00'],\n        },\n        yAxis: {\n          type: \"value\",\n          axisLabel: {\n            formatter: \"{value} T\",\n          },\n          axisPointer: {\n            snap: true,\n          },\n        },\n        visualMap: {\n          show: false,\n          dimension: 0,\n          pieces: msg.pieces,\n        },\n        series: [\n          {\n            name: \"avg\",\n            type: \"bar\",\n            itemStyle: {\n              //color: 'rgba(190, 190, 190, 0.4)',\n              opacity: 0.4,\n            },\n            tooltip: {\n              valueFormatter: function (value) {\n                return value + \" T\";\n              },\n            },\n            data: msg.tons_pw,\n            color: [\"#ace\"],\n            // color:['#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE','#BEBEBE'],\n            //[6945,4967,7994,4510,8395,5413,8662,7703,7826,8099,8135,6557],\n            barWidth: \"85%\",\n          },\n\n          {\n            name: \"Tons\",\n            type: \"line\",\n            smooth: true,\n            // prettier-ignore\n            data: msg.tons,\n            color: [\"green\"],\n            markArea: {\n              itemStyle: {\n                color: \"rgba(255, 173, 177, 0.4)\",\n              },\n              data: [msg.mark],\n            },\n          },\n        ],\n      });\n    }\n  });\n\n\n\n}\n\nlet interval = setInterval(() => {\n    if (window.echarts) {\n        // call an init() to use BABYLON\n        init();\n        // Babylon.js is loaded, so we can now use it\n        clearInterval(interval);\n    }\n}, 100);\n\n\n</script>\n","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":420,"y":1980,"wires":[[]]},{"id":"b0dad8343feda1c6","type":"ui-group","name":"Input","page":"0405dc4a843d1793","width":"12","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"0405dc4a843d1793","type":"ui-page","name":"Report Builder","ui":"d726187aa6c1921a","path":"/page1","icon":"home","layout":"grid","theme":"ba2e667d0985ce12","order":-1,"className":"","visible":"true","disabled":"false"},{"id":"d726187aa6c1921a","type":"ui-base","name":"UI Name","path":"/dashboard"},{"id":"ba2e667d0985ce12","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094CE","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]
1 Like

Thank you @UnborN that certainly takes me in the right direction. The static data is rendering now. However, an error is being thrown.
image
I don't know what this means but it is pointing to this highlighted line of code:


These errors are being thrown continuously before any data is injected into the node.

Here is a very basic working demo to get you moving.

chrome_3bl8y1grck

hook these 2 injects up to the input of your template

[{"id":"2d2e714030317eee","type":"inject","z":"85fb8b6df2be7ac8","name":"","props":[{"p":"payload"},{"p":"payload.title","v":"Average per hour","vt":"str"},{"p":"payload.labels","v":"[\"07:00\",\"08:00\",\"09:00\",\"10:00\",\"11:00\",\"12:00\",\"13:00\",\"14:00\",\"15:00\",\"16:00\",\"17:00\",\"18:00\"]","vt":"json"},{"p":"payload.data","v":"[8600, 8750, 7800, 8700, 9600, 6400, 5600, 4750, 5980, 6000, 5555, 5150]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"data","payload":"{}","payloadType":"json","x":1210,"y":540,"wires":[["29ee8b5b2da056b6"]]},{"id":"b0e5da946de25ea9","type":"inject","z":"85fb8b6df2be7ac8","name":"","props":[{"p":"payload"},{"p":"payload.title","v":"Tons / Hour","vt":"str"},{"p":"payload.labels","v":"[\"07:00\",\"08:00\",\"09:00\",\"10:00\",\"11:00\",\"12:00\",\"01:00\",\"02:00\",\"03:00\",\"04:00\",\"05:00\",\"06:00\"]","vt":"json"},{"p":"payload.data","v":"[5300, 9280, 11250, 1260, 2270, 4300, 5550, 2500, 2400, 4390, 9380, 12390, 10400, 11500, 7600, 8750, 4800, 8700, 9600, 4400, 6600, 6750, 8980, 7000]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"data","payload":"{}","payloadType":"json","x":1210,"y":580,"wires":[["29ee8b5b2da056b6"]]}]

Here is the template code - its not pretty but it works (I will leave it to you to re-arrange it for the parts you want to automate)

<template>
    <div ref="charttpw" style="width: 500px; height: 200px"></div>
</template>

<script type="text/javascript" src="https://fastly.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>

<script>

    export default {
        data() {
            return {
                myChart: null
            }
        },
        watch: {
            msg: function () {
                if (this.msg.topic === "data") {
                    this.update(this.msg.payload.labels, this.msg.payload.data, this.msg.payload.title)
                }
            }
        },
        mounted() {
            let interval = setInterval(() => {
                if (window.echarts) {
                    clearInterval(interval);
                    // now it is loaded, we can initialise and use it
                    this.init();
                }
            }, 100);
        },
        methods: {
            init: function () {
                this.myChart = echarts.init(this.$refs.charttpw, "dark");
                // dummy / test data
                const labels = ['07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00']
                const data = [5300, 9280, 11250, 1260, 2270, 4300, 5550, 2500, 2400, 4390, 9380, 12390] 
                const title = "Tons per Hour"
                this.update(labels, data, title)
            },
            update: function (xAxisData, data, title) {
                this.myChart.setOption({
                    title: {
                        text: title
                    },
                    tooltip: {
                        trigger: "axis",
                        axisPointer: {
                            type: "cross",
                        },
                    },
                    toolbox: {
                        show: true,
                        feature: {
                            saveAsImage: {},
                        },
                    },
                    grid: {
                        left: "3%",
                        right: "4%",
                        //top: '30%',
                    containLabel: true,
                    },
                    xAxis: {
                        type: "category",
                        boundaryGap: false,
                        data: xAxisData,
                    },
                    yAxis: {
                        type: "value",
                        axisLabel: {
                            formatter: "{value} T",
                        },
                        axisPointer: {
                            snap: true,
                        },
                    },
                    visualMap: {
                        show: false,
                        dimension: 0,
                        pieces: [
                            { lte: 9, color: "green" },
                            { gt: 9, lte: 11, color: "red" },
                            { gt: 11, color: "green" },
                        ],
                    },
                    series: [{
                        name: "Tons",
                        type: "line",
                        smooth: true,
                        // prettier-ignore
                        data: data,
                        markArea: {
                        itemStyle: {
                            color: "rgba(255, 173, 177, 0.4)",
                        },
                        data: [[{ name: "Max Peak", xAxis: "9:00" }, { xAxis: "11:00" }]],
                        },
                    }],
                });
            }
        }
    }
</script>

2 Likes

Thank you very much @Steve-Mcl . That gets me over the line!

For what it's worth - we are likely to be switching ChartJS out for Apache ECharts in the near future: Investigate Apache ECharts as a ChartJs alternative for ui-chart · Issue #782 · FlowFuse/node-red-dashboard · GitHub

5 Likes

Would you mind sharing your finished code? I’ve been struggling to get 3rd party libraries to work right and these charts look great. I would like to start using them even if chartjs does eventually get replaced by them.

Thank you in advance.

We have been using Echarts for real time data display in Dashboard 1, since Echarts is fast and has lots of configuration options.

We compared multiple different opensource charts in terms of performance, and Echarts is on top.

This isn't much different than the solution provided by @Steve-Mcl other than adapting to my data flow. The bars in the chart are only updated once per day so that data resides in a context variable. The line data is updated every few minutes.
tph.json (16.7 KB)
I am not confident I am calling the resize event correctly, however, what I have works better than no resize event. I am still learning D2 as well.
Hope this helps.