Using Highcharts within a Vue.js component

I'm having trouble creating graphical components with Highcharts and Vue.js because I can't figure out how to dynamically set the id attribute that Highcharts needs to render properly.

Does anyone know how to set the id dynamically?

This is the HTML code snippet:

<objective-chart :element="'brick-chart'"></objective-chart>

And here's the JavaScript code snippet:

<template>
    <div id="{{element}}"></div>
</template>

<script>
    import Highcharts from 'highcharts';
    export default{
        props: ['element'],
        created(){
            $(function () {

                new Highcharts.Chart({
                    chart: {
                        renderTo: this.element,
                        type: 'bar',
                        height: 200,
                        margin: [0, 20, 0, 40]
                    },
                    title: {
                        text: null
                    },
                    xAxis: {

                        lineColor: null,
                        labels: {
                            rotation: -90
                        },
                        categories: [
                            'Brick'
                        ]
                    },
                    yAxis: [{

                        min: 0,
                        max:100,
                        endOnTick: true,
                        maxPadding: 0.02,
                        gridLineColor: null,

                        title: {
                            text: null
                        },
                        labels: {
                            y: -50
                        },


                    }],
                    legend: {
                        shadow: false,
                        verticalAlign: 'bottom'
                    },
                    tooltip: {
                        shared: true,
                        followPointer: true
                    },
                    plotOptions: {
                        column: {
                            grouping: true,
                            shadow: false,
                            borderWidth: 0
                        }
                    },
                    credits: {
                        enabled: false
                    },
                    series: [{
                        name: 'Objective',
                        color: 'rgba(224,224,224,1)',
                        data: [100],
                        pointPadding: 0.3,
                        pointPlacement: -0.2
                    }, {
                        name: 'Actual',
                        color: 'rgba(106,166,46,.9)',
                        data: [76],
                        pointPadding: 0.4,
                        pointPlacement: 0.1
                    }, {
                        type:'spline',
                        name: 'Projection',
                        color: 'rgba(106,166,46,.9)',
                        top: 10,
                        pointPlacement: -0.05,
                        data: [95],
                        marker: {
                            radius: 8,
                            lineColor: '#666666',
                            lineWidth: 1
                        }
                    }]
                });
            });
        }
    }
</script>

Answer №1

vue.js 2.0 example demonstrating the use of virtual dom in Vue:
1) Execute npm install highcharts
2) Use

var Highcharts = require('highcharts');

3) Call Highcharts.chart(this.$el, {...}) inside the "mounted" method as this.$el is only accessible after that lifecycle hook
4) Remember to destroy the instance of highcharts in the "beforeDestroy" method.

<template>
<div><div>
</template>

<script>
var Highcharts = require('highcharts');
export default {
    name : "Chart",
    props : {
      series : {
        type: Array,
        required: true
      }
},
  data : function() {
      return {
        target: undefined
      }
    },
    mounted : function() {
      this.target = Highcharts.chart(this.$el, {
        title: {
          text: 'Monthly Average Temperature',
          x: -20 //center
        },
        subtitle: {
          text: 'Source: WorldClimate.com',
          x: -20
        },
        xAxis: {
          categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
          'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        },
        yAxis: {
          title: {
          text: 'Temperature (°C)'
        },
        plotLines: [{
          value: 0,
          width: 1,
          color: '#808080'
        }]
      },
      tooltip: {
        valueSuffix: '°C'
      },
      legend: {
        layout: 'vertical',
        align: 'right',
        verticalAlign: 'middle',
          borderWidth: 0
      },
      series: this.series
    });
  },
  beforeDestroy: function() {
    this.target.destroy();
  },
}
</script>

The parent component would be:

<template>
  <div id="app">
    <h1>{{ msg }}</h1>
    <Chart :series = "initSeries"></Chart>
  </div>
</template>

<script>
import Chart from './Chart.vue';
export default {
  name: 'app',
  components : {Chart},
  data () {
    return {
      msg: 'Welcome to Your Vue.js App',
    }
  },
  computed : {
    initSeries : function() {
      return [{

              name: 'Tokyo',
              data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
          }, {
              name: 'New York',
              data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
          }, {
              name: 'Berlin',
              data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
          }, {
              name: 'London',
              data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
          }];

  
     }
   }
}
</script>

Answer №2

Update: Make sure to see the Vue 2 demonstration by @Tody.Lu, which offers an excellent solution.

To ensure a properly formatted ID selector, utilize renderTo: "#" + this.element.

Alternatively, you may use renderTo: this.$el without specifying an ID at all.

Update: After reviewing my Highcharts component, this is the setup I have:

$(this.$el).highcharts(data);

This method eliminates the necessity for an ID.

Answer №3

If you are utilizing a central data store like Vuex, consider adding a chart increment property to keep track of the number of charts created and automatically increment it when a new one is added.

To assign an ID, you can utilize a computed property:

computed: {
  id () {
    return 'chart-' + idValue
  }
}

While it may be tempting to store it in a global variable, that approach is not recommended.

Alternatively, you could generate a random string within your component. One method I have used in the past involves using the UUID generator referenced in this response.

If you choose to use the UUID function UUID.generate() to produce a random string:

data () {
  return {
    uniqueId: UUID.generate()
  } 
}

You can then incorporate the generated uniqueId property into a computed property:

computed: {
  id () {
    return 'chart-' + this.uniqueId
  }
}

This allows you to reference {{ id }} in your Vue instance.

Answer №4

Be cautious, in your template there is an error:

<template>
    <div><div>
</template>

You should correct it to this:

<template>
    <div></div>
</template>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for automatically verifying coupons and adjusting prices

My current task involves implementing a coupon feature on the checkout page using an AJAX request to validate the coupon and adjust the price accordingly. However, when the checkout view is loaded, I encounter an error message: The first argument in the ...

verified firebase/firestore requests

I've been struggling with the process of sending authenticated firebase/firestore calls. I set up firestore in my web app using Next.js as shown below: import { initializeApp } from "firebase/app"; import { getFirestore } from 'firebase ...

Preventing Angular $rootElement.on('click') from affecting ReactJS anchor tag interactions

Running both AngularJS and ReactJS on the same page has caused an issue for me. Whenever I click on a ReactJS <a> tag, Angular's $rootElement.on('click) event is triggered and the page redirects. I need to perform some functionality in Re ...

Utilize Optional Chaining for verifying null or undefined values

I have utilized the following code: data?.response[0]?.Transaction[0]?.UID; In this scenario, the Transaction key is not present, resulting in the error message: ERROR TypeError: Cannot read properties of undefined (reading '0') Instead of chec ...

Discovering active path while utilizing dynamic routes - here's how!

Whenever I click on the project element in my HeadlessCMS with the URL /projects/slug-name, the projects button in my Navbar (LinkItem) does not highlight with a background color (bgColor). How can I modify this line of code: const active = path === href / ...

The returned JSON object lacks a specified name

After receiving the JSON data from the server, I noticed an unnamed node within the 'someStuff' object: { "someStuff": { "": { "foo": 0 }, "moreStuff": { "foo": 2 } } } This raises ...

Preventing an infinite re-render loop caused by event listeners in React

One functional component is causing me some trouble: export default function Nav({photo}) { const [isOpen, setIsOpen] = useState(false) const [width, setWidth] = useState(window.innerWidth); const breakpoint = 768; useEffect(() => { ...

Display the dropdown selected value within a Laravel Blade template

I am facing an issue with passing the selected value from a drop-down to another Blade file in Laravel. I have tried using Ajax and jQuery, but it doesn't seem to work for me. I want to display the selected value on the content.blade.php page without ...

Error encountered: jQuery AJAX JSON request failed to be caught

While my WordPress AJAX process is successful, a peculiar error keeps popping up in Chrome Devtools: Uncaught TypeError: Cannot read property 'vehicle' of undefined. It's puzzling, as the parsed JSON data seems to be in the correct object fo ...

Exploring the use of leaflets within LitElement

I have been working on a project involving LitElement components and I am looking to incorporate Leaflet into it. However, I am encountering difficulties with displaying the map properly. After installing Leaflet through npm in my project, I created a clas ...

Passing all emitted events from Vue 3 child component to its parent - A complete guide

My Vue components are structured as follows: <TopParent> <!-- Listening for events from EventProducer here --> <Child_1> <Child_2> <Child_3> ... <Child_N> <EventProducer /> &l ...

Transferring the AJAX response into a JavaScript variable

New to AJAX and JS here. I am implementing an AJAX code that fetches data from a php service. I am trying to figure out how to store the returned data in a JavaScript variable, which I can then display on the UI. Below is my AJAX code snippet: <script ...

Find the specific element that is visible within a customized viewport, such as a div or ul

Exploring the capabilities of the Viewport Selectors for jQuery plugin, here is a snippet of its source code: (function($) { $.belowthefold = function(element, settings) { var fold = $(window).height() + $(window).scrollTop(); return fold <= $ ...

Node.js is essential when using Angular for implementing ui-select components

I'm currently delving into learning AngularJS. I've successfully created a basic web application using AngularJS, with Java EE powering the backend (server side). This app is being hosted on Tomcat. The advantages of AngularJS over JQuery are bec ...

Using Javascript code within functions.php

I am facing an issue with the code below; function add_js_functions(){ $gpls_woo_rfq_cart = gpls_woo_rfq_get_item(gpls_woo_rfq_cart_tran_key() . '_' . 'gpls_woo_rfq_cart'); if(is_array($gpls_woo_rfq_cart)){ $count = count($gpls_woo_r ...

How to send parameters to the jQuery delete button click event handler

Here is the jQuery code I am working with: $('#btnDelete').click( function() {//Do the delete here via jquery post}); In my table, each row has a delete button like this: <a id="btnDelete">Delete</a> I need to pass parameters to t ...

I'd like to know how to retrieve the start and end dates of a specific month using JavaScript

How can I retrieve the start and end date of the current month? const currentDate = new Date(); const startOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1); const endOfMonth = new Date(currentDate.getFullYear(), currentD ...

Is there a way for me to adjust the image dimensions so that it doesn't surpass the width of its parent container?

When working with images, it can be tricky to set the original width while also ensuring it fits within a parent container. For example, if the parent container has a width of 1000px, you may want the image to have a max-width of 100%, but not exceed 1000p ...

The presence of an unfamiliar custom element, specifically <v-btn>, was detected following the installation of V

I can't figure out why my code isn't functioning properly. I have created a file at src/plugins/vuetify.ts with the following content: import Vue from "vue"; import Vuetify from "vuetify/lib"; Vue.use(Vuetify); const vuetify ...

Next.js: An absence of response is observed when a high volume of requests is made on a server-side rendering page with

Currently, I am utilizing Next.js along with a custom server (express js) as demonstrated in the GitHub example. For instance, I have a page located at “/post/[id]” that makes use of Next.js dynamic routing. The issue arises when the number of request ...