Skip to content

Vue v3 Highcharts (no build)

Julian Knight edited this page Jul 15, 2022 · 1 revision

This is an example of using Highcharts with Node-RED, uibuilder, Vue v3 and the official vue-highcharts support library. An non-uibuilder example for Vue v2 exists here.

Note that is uses the IIFE version of the uibuilder front-end library from uibuilder v5.1.1+.

Sorry, no example of updating the data in this. Only getting the libraries to work. However, this is also an example of using the Quasar framework, also with no build step.

index.html

<!doctype html>
<html lang="en"><head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Minimal modern client example - Node-RED uibuilder</title>
    <meta name="description" content="Node-RED uibuilder - Minimal modern client example">
    <link rel="icon" href="./images/node-blue.ico">

    <link href="https://cdn.jsdelivr.net/npm/quasar@latest/dist/quasar.prod.css" rel="stylesheet" type="text/css">
    <!-- <link type="text/css" rel="stylesheet" href="./index.css" media="all"> -->

</head><body class="uib">
    
    <h2>uibuilder Minimal Modern Client Example using IIFE library</h2>

    <div id="q-app" class="q-ma-md">
        <q-btn id="sendToNR" color="primary" @click="doEvent" data-from="from client" data-something="else">
            Send <br><code>data-*</code> attribs to Node-RED
        </q-btn>
        <q-btn id="sendToNR2" color="primary" @click="doSend" data-from="from client using eventSend" data-something="else">
            Send to Node-RED
        </q-btn>

        <div class="q-ma-md">
            <q-btn label="Notify" color="primary" @click="fnNotify"></q-btn>
        </div>

        <div class="q-ma-md">
            Running Quasar v{{ $q.version }}
        </div>

        <syntax-highlight auto="msg">Latest msg from Node-RED:</syntax-highlight>

        <div class="title-row">
            <p>Set the chart title here:</p>
            <input type="text" v-model="title">
        </div>
        <highcharts :options="chartOptions"></highcharts>
    </div>

    <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / -->
    <script src="https://cdn.jsdelivr.net/npm/vue@latest/dist/vue.global.prod.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@latest/dist/quasar.umd.prod.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@latest/dist/lang/en-GB.umd.prod.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@latest/dist/icon-set/svg-material-icons.umd.prod.js"></script>
    <script src="https://code.highcharts.com/highcharts.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/highcharts-vue@latest/dist/highcharts-vue.min.js"></script>
    <script src="../uibuilder/uibuilder.iife.min.js">/* REQUIRED. NB: socket.io not needed */</script>
    <script src="./index.js">/* OPTIONAL: Put your custom code here */</script>
    <!-- #endregion -->

</body></html>

index.js

// @ts-nocheck

/** Minimalist code for uibuilder and Node-RED */
'use strict'

// return formatted HTML version of JSON object
import('../uibuilder/vendor/@totallyinformation/web-components/components/syntax-highlight.js')
const { useQuasar } = Quasar

// Send a message back to Node-RED
window.fnSendToNR = function fnSendToNR(payload) {
    uibuilder.send({
        'topic': 'msg-from-uibuilder-front-end',
        'payload': payload,
    })
}

// Using the Vue options API style for beginner simplicity
// No need to pre-define Quasar's $q when working with the options API
const app = Vue.createApp({
    // Define Vue reactive variables
    data() { return {
            count: 0,

            chartOptions: {
                chart: {
                    type: 'spline'
                },
                title: {
                    text: 'Entire title'
                },
                series: [{
                    data: [10, 0, 8, 2, 6, 4, 5, 5]
                }]
            },
            title: ''
    } },

    watch: {
        title(newValue) {
            if (newValue === '') {
                    this.chartOptions.title.text = 'Entire title'
            } else {
                    this.chartOptions.title.text = newValue
            }
        }
    },

    // Reactive functions
    methods: {
        increment() {
            this.count++
        },

        fnNotify() {
            this.$q.notify('Running on Quasar v' + this.$q.version)
        },

        // Use the uib helper function to send something to NR
        doEvent(event) { uibuilder.eventSend(event) },

        // Use the normal send fn to send something to NR
        // NOTE: You cannot pass the domevent, domevent.currentTarget, or domevent.path[0] direct, you have to access specific properties
        doSend(domevent) {
            console.log('>> doSend >>', domevent)

            uibuilder.send({
                'topic': 'msg-from-uibuilder-front-end',
                'payload': payload,
            })
        },
    },

    // Lifecycle hooks
    created() {
        // No need to pre-define $q when working with the options API
        console.log('$q', this.$q)
        console.log(`>> Is Dark Active: ${this.$q.dark.isActive}, Dark Mode: ${this.$q.dark.mode}`)
    },

    mounted() {
        console.log(`The initial count is ${this.count}.`)

        // If msg changes - msg is updated when a standard msg is received from Node-RED
        uibuilder.onChange('msg', function (msg) {
            console.log('>> msg recvd >>', msg)
            Quasar.Notify.create('New message from Node-RED!')
            app.lastMsg = msg
        })
    },
})

app.use(HighchartsVue.default)
app.use(Quasar, {
    config: {
        dark: 'auto' // or Boolean true/false
    }
})
Quasar.lang.set(Quasar.lang.enGB)
Quasar.iconSet.set(Quasar.iconSet.svgMaterialIcons)
app.mount('#q-app')
Clone this wiki locally