Uibuilder: How to set the title property of an Apex chart?

Ahoi,

with @TotallyInformation's uibuilder I'm happily displaying various charts on my dashboard. The updating works as well, but I never came around the problem of changing the title of an Apex chart that is configured through an options object. Here's what I have:

index.js

'use strict'

function getTreeMapLabelOptions(fontSize, fontWeight, opacity, useShadow) { return {
    enabled: true,
    style: {
        fontFamily: 'Helvetica, Arial, sans-serif',
        fontSize: fontSize + 'px',
        fontWeight: fontWeight,
    },
    offsetY: -4
}}


function getTreeMapOptions(chartTitle, labelOptions) { return {
    legend: { show: false },
    chart: {
        height: 600,
        type: 'treemap'
    },
    title: { text: chartTitle },
    dataLabels: labelOptions,
    plotOptions: {
        treemap: {
            enableShades: true,
            shadeIntensity: 0.3,
            reverseNegativeShade: true,
            distributed: false
        }
    }
}}

/** Reference the apexchart component (removes need for a build step) */
Vue.component('apexchart', VueApexCharts)

// eslint-disable-next-line no-unused-vars
var app1 = new Vue({
    el: '#app',
    data: {
        startMsg: 'Vue has started, waiting for messages',
        optionsTreeMap : getTreeMapOptions("Utilities", getTreeMapLabelOptions(64, 'bold',      0, false)),
        seriesTreeMap: [ { data: [ { x : 'A', y: 25 }, { x : 'B', y: -3 }, { x : 'C', y: 4 }, { x : 'D', y: 53 }, { x : 'E', y: 33 } ] } ] // demo data to display right away
},
    computed: { },
    methods: {},
    // Available hooks: init,mounted,updated,destroyed
    mounted: function() {
        uibuilder.start()
        var vueApp = this
        // Process new messages from Node-RED
        uibuilder.onChange('msg', function (newMsg) {
            if (newMsg.update === "updateTreeMap" && newMsg.newSeriesData instanceof Array) {
                vueApp.seriesTreeMap = newMsg.newSeriesData;

                // None of the following works:
                //vueApp.optionsTreeMap['title'] = { text : 'Utilities_TitleChanged' };
                //vueApp.optionsTreeMap.set('title', { text : 'Utilities_TitleChanged' });
            }

index.html:

<!doctype html><html lang="en"><head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">

    <title>ApexChart/VueJS - TreeMap charts</title>
    <meta name="description" content="TreeMaps with Apex charts">

    <link rel="icon" href="./images/node-blue.ico">

    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css" />

    <link rel="stylesheet" href="./index.css" media="all">
</head><body>
    <div id="app">
        <b-container id="app_container">

            <h1>Demo charts with Apex</h1>

            <b-row>
                <b-card col class="w-50" header="TreeMap" border-variant="primary" header-bg-variant="primary" header-text-variant="white" align="center">
                    <apexchart height="350" :options="optionsTreeMap" :series="seriesTreeMap"></apexchart>
                </b-card>
            </b-row>

        </b-container>
    </div>

    <script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
    <script src="../uibuilder/vendor/vue/dist/vue.min.js"></script>
    <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script>

    <!-- Loading from CDN, use uibuilder to install packages and change to vendor links -->
    <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue-apexcharts"></script>

    <script src="./uibuilderfe.min.js"></script> <!--    //prod version -->
    <script src="./index.js"></script>

</body></html>

Now as mentioned above, updating the treeMap works nicely:
image

The message I'm sending to the uibuilder node is as follows:

var newMsg = {
    newSeriesData: { data: msg.payload }, // msg.payload is simply an array with x and y entries (see Apex documentation)
    update: "updateTreeMap"
}

return newMsg;

Now my question to you is: How can I define the title of a chart per update?

When I use the debugger I see that the update had obviously changed the title : text to 'Utilities_TitleChanged', but the chart does not update visually.

Any ideas would be highly appreciated.

Best regards
Marcel

Hello Marcel, hows it going ?

yes .. this is a common problem with Vue's reactivity regarding deep nested objects or when changing specific elements in an array. Vue has an issue detecting those changes and then updating the DOM.

I'm guessing you have already read the article on Vue's official website regarding Reactivity in Depth since i see in your commented out code the attempt to use Vue.set

One way to get it to work is to use Object.assign like this :

vueApp.optionsTreeMap = Object.assign({}, vueApp.optionsTreeMap, { title: { text: 'Utilities_TitleChanged' } })

this way you basically merge the new title.text value to the existing optionsTreeMap object and force Vue to detect the change and update the Apex component.

1 Like

Hi mate!

Thanks for this article. I wasn't aware of that one. The project I am working on is quite demanding with lots of crazy combinations of queries on SQL and Mongo databases together with displaying their results in charts, etc.
It's pretty massive stuff, and I'm happy if my partner and me make good meters in a week so I'm often not looking after smaller details that are not 100% perfect, but work OK for us and where getting them the 100% perfect easily takes up many hours (and sometimes just to figure out that it's not possible to get the extra saucage .. :grimacing:)

But again, good souls like you happen to come around with brilliant ideas, and I'm really thankful for your help! I'll give it a try and let you know if it works. If there is anything I can contribute back in any form, let me know!

Update: Your solution works like a charm!! Thanks so much!

Cheers,
Marcel

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.