DB2 html-template chartjs

DB2 html-template chartjs

I am desperately trying to use this example based on this minimal example (modified as a line graph):

https://dashboard.flowfuse.com/nodes/widgets/ui-chart#building-custom-charts

With the help of the annotation plugin
https://www.chartjs.org/chartjs-plugin-annotation/latest/guide/integration.html

I just want to draw an annotation line. But no matter what I do, nothing is rendered.

What am I doing wrong? Or is the annotation plugin incompatible with DB2?

Here is my sample code:

<template>
    <canvas ref="chart" />
</template>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation"></script>

<script>
  export default {
        mounted() {
            // code here when the component is first loaded
            let interval = setInterval(() => {
                // wait until Chart and the annotation plugin are available globally
                if (window.Chart && (window.ChartAnnotation || window.chartjsPluginAnnotation)) {
                    clearInterval(interval);
                    // register plugin globally (cover different global names)
                    const plugin = window.ChartAnnotation || window.chartjsPluginAnnotation;
                    try {
                      // Chart.js tolerates multiple registrations, but check to be safe
                      if (!Chart.registry._plugins.list.includes(plugin)) {
                        Chart.register(plugin);
                      }
                    } catch(e){
                      // fallback: just register
                      Chart.register(plugin);
                    }
                    this.draw()
                }
            }, 100);
        },
        methods: {
            draw () {
                const ctx = this.$refs.chart
                new Chart(ctx, {
                    type: 'line',
                    data: {
                        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
                        datasets: [{
                            label: '# of Votes',
                            data: [12, 19, 3, 5, 2, 3],
                            borderWidth: 1,
                            borderColor: 'rgba(54,162,235,1)',
                            backgroundColor: 'rgba(54,162,235,0.2)',
                            fill: false
                        }]
                    },
                    options: {
                        plugins: {
                            // configure annotation plugin
                            annotation: {
                                annotations: {
                                    // simple horizontal line at y = 8
                                    yLine: {
                                        type: 'line',
                                        // yMin and yMax equal => horizontal line
                                        yMin: 8,
                                        yMax: 8,
                                        borderColor: 'red',
                                        borderWidth: 2,
                                        borderDash: [6,4],
                                        // label on the line
                                        label: {
                                            enabled: true,
                                            content: 'Schwellenwert 8',
                                            position: 'end',
                                            backgroundColor: 'rgba(0,0,0,0.7)',
                                            color: '#fff',
                                            font: {
                                                size: 12
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        scales: {
                            y: {
                                beginAtZero: true
                            }
                        }
                    }
                });
            }
        }
    }
</script>

I don’t use that particular plug-in but there is sample working code for chart.js in ui-template in this post. Working code - Chart.js and ui-template.

Hope this helps.

Thanks for your help
The problem is not the general creation of charts in the html template.
My original template runs as a multi-axis line chart without any problems.

I just can't get the annotation plugin to work.
Neither in my original template nor in the minimal version.

I do not think you need to register the plugin. According to the Annotation use page all that is required is the script source lines and then draw()

<script src="path/to/chartjs/dist/chart.min.js"></script>
<script src="path/to/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.min.js"></script>
<script>
    var myChart = new Chart(ctx, {...});
</script>

The registration is only required for Bundlers.

I've been working on this for three hours. It seems like the annotation module doesn't work properly along with Vue dashboard.

Oh, I'm sorry you invested so much time. I'm giving up for now too :wink:

I haven't been able to do that yet either. Is there an example somewhere of how to use it in the DB2 template node?

This shows the graph and looking at the page info (Ctrl 12) I can see that the annotation file is loaded, but, like others so far no annotation line;

<template>
    <canvas ref="chart" />
</template>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation"></script>


<script>
    export default {
        data() {           
            return {
                isChartLoaded: false,
                chartTitle: '',
                             
            }
        },
        
        async mounted() {
            await this.$nextTick()

            this.draw()
 
            this.isChartLoaded = true
            this.send({loaded: this.isChartLoaded})

        },

        methods: {
            draw () {
1 Like

Yes, that's as far as I've got so far.
Unfortunately, I'm not a web developer. :downcast_face_with_sweat:

What kind of chart are you looking for ?


example using echarts instead:

<template>
  <div id="chart" style="width: 100%; height: 400px;"></div>
</template>

<script src="https://cdn.jsdelivr.net/npm/echarts@6.0.0/dist/echarts.min.js"></script>

<script>
  export default {
  mounted() {
    setTimeout(() => {
      if (window.echarts) {
        // use DOM element ID - refs will not function properly. 
        const chartDom = document.getElementById('chart');
        if (!chartDom) {
          console.error('Chart container element not found');
          return;
        }

        this.chart = echarts.init(chartDom);

        const option = {
          title: { text: 'Votes' },
          tooltip: { trigger: 'axis' },
          legend: { show: false },
          xAxis: {
            type: 'category',
             data:['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange']
          },
          yAxis: {
            type: 'value'
          },
          series: [{
            name: '# of Votes',
            type: 'line',
             data:[12, 19, 3, 5, 2, 3],
            markLine: {
              data: [{ type: 'average', name: 'Avg' }],
              lineStyle: { color: 'red' }
            }
          }]
        };

        this.chart.setOption(option);
      } else {
        console.error('ECharts library not loaded yet');
      }
    }, 400); 
  }
};
</script>

<style>
  /* Optional styling */
</style>

Note the

// use DOM element ID - refs will not function properly.

comment, i can imagine that the annotation plugin you are trying to use encounters the same reactivity issue.

1 Like

Curious as to why you say that? In my echarts example here, ref works fine.

Until it doesn't, certain properties are not working properly due to the way vue is handling proxied data. See the notes on echarts and github. In general it will (seem to) work.

In this case for example, the tooltip will not work when it is set to axis, but will work when set to item.

1 Like

Ok, thanks for the link. My issue with instructing people to use an ID is that this becomes less reusable? I thought for a minute that you were saying it must use an ID! I.e. that not using the ID is the problem where it appears the reason for being advised not to use ref is actually because a ref makes it a reactive proxy object.

A lot of words to say I would not promote the use of fixed ID. I wonder if wrapping it in a div with a ref then using regular dom call on the ref to get a non-reactive Dom object would be a better approach. e.g

const chart = this.$refs.wrapper.querySelector('.inner-element');

That looks fantastic. Thank you very much. eCharts seems to be a real alternative. It's time to take a closer look at it.

I am not sure if this would work, vue has a method to accomodate for this behaviour, where you can exclude properties from becoming reactive, but I don't fully grasp what it would imply when used.

that you were saying it must use an ID!

It is more that you can expose the chart as an object that is not reactive, it can then still be updated from vue.

A quick conversion. It's quite simple and does exactly what it should. Now some proper styling, then it's just as it should be.

Thanks again for the tip