Using Vue.js

In this tutorial we will add amCharts 4 to a Vue.js app.

Setting up

We will use Vue CLI v.3 (beta 16 at the time of this writing) to scaffold the starter Vue app like this:

npx @vue/cli create my-chart-project

We will choose the "default" preset (babel, eslint) for the most common scenario.

Let’s make sure that everything got created as expected. Switch to our project directory:

cd my-chart-project

And run the dev server:

npm run serve

You should see a standard Vue.js starter page when you navigate to http://localhost:8080.

Now open the HelloWorld component (/src/components/HelloWorld.vue) in your code editor of choice and remove everything inside the root DIV in the template, unnecessary CSS declarations and code. And add CSS to set the size of our main DIV and a REF that we will use later to tell amCharts where to render the chart.

Your component should look something like this:

<template>
  <div class="hello" ref="chartdiv">
  </div>
</template>

<script>
export default {
  name: 'HelloWorld'
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
  width: 100%;
  height: 500px;
}
</style>

Adding charts

Now let’s add amCharts.

Install amCharts 4 from npm:

npm install @amcharts/amcharts4

Import amCharts libraries in the script portion of your component:

import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
import am4themes_animated from "@amcharts/amcharts4/themes/animated";

am4core.useTheme(am4themes_animated);

Add the mounted() method to your component:

export default {
  name: 'HelloWorld',
  mounted() {
    // we will create the chart here
  }
}

NOTE If you want to support older browsers, make sure you set up polyfills. Click here for detailed instructions.

And implement chart creation code in it so you whole component looks like this:

<template>
  <div class="hello" ref="chartdiv">
  </div>
</template>

<script>
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
import am4themes_animated from "@amcharts/amcharts4/themes/animated";

am4core.useTheme(am4themes_animated);


export default {
  name: 'HelloWorld',
  mounted() {
    let chart = am4core.create(this.$refs.chartdiv, am4charts.XYChart);

    chart.paddingRight = 20;

    let data = [];
    let visits = 10;
    for (let i = 1; i < 366; i++) {
      visits += Math.round((Math.random() < 0.5 ? 1 : -1) * Math.random() * 10);
      data.push({ date: new Date(2018, 0, i), name: "name" + i, value: visits });
    }

    chart.data = data;

    let dateAxis = chart.xAxes.push(new am4charts.DateAxis());
    dateAxis.renderer.grid.template.location = 0;

    let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
    valueAxis.tooltip.disabled = true;
    valueAxis.renderer.minWidth = 35;

    let series = chart.series.push(new am4charts.LineSeries());
    series.dataFields.dateX = "date";
    series.dataFields.valueY = "value";

    series.tooltipText = "{valueY.value}";
    chart.cursor = new am4charts.XYCursor();

    let scrollbarX = new am4charts.XYChartScrollbar();
    scrollbarX.series.push(series);
    chart.scrollbarX = scrollbarX;

    this.chart = chart;
  },

  beforeDestroy() {
    if (this.chart) {
      this.chart.dispose();
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
  width: 100%;
  height: 500px;
}
</style>

You're all set! You should see something like this in your browser:

 

IMPORTANT Do not include the chart object inside your Vue component's data property. Vue's reactivity system conflicts with how amCharts manages updates to the chart object and can cause errors if you do this. If you need to store a reference to the chart object in your component, create your reference variable inside the created hook, then assign your chart instance to it in your  mounted hook.

Important note

Don't put amCharts objects inside of the component's data, it will cause errors. Instead, just use a regular property (like in the above example).

You can still use data and props, but you will need to use lifecycle hooks in order to update amCharts when they change:

export default {
  data() {
    return {
      foo: 5,
    };
  },

  props: {
    bar: Number,
  },

  watch: {
    foo(newValue, oldValue) {
      if (this.chart) {
        // Update chart based on foo data
        ...
      }
    }
  },

  updated() {
    if (this.chart) {
      // Update chart based on props
      ...
    }
  },

  ...
}