Vue.js and Chart.js are two popular javascript libraries, today we are going to learn how to draw a chart for Covid-19 using Open data on COVID-19 in Malaysia.

For beginners to learn Vue.js, sometimes it is simpler to code directly using an HTML with javascript file and a browser instead of using Node.js and  Vue CLI, so this post will use this approach. To add all the javascript libraries to the  HTML, we will use external CDN and script tags.

  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>  <script src="https://unpkg.com/vue@^2/dist/vue.js"></script>  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>  <script src="https://unpkg.com/vue-chartjs/dist/vue-chartjs.js"></script>  <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.1/papaparse.min.js"></script>  

Above are the libraries we will use, they are:

  1. Vue.js - A Progressive JavaScript Framework.
  2. Chart.js - A simple, clean and engaging HTML5 based JavaScript charts.
  3. Vue-Chartjs - A wrapper for Chart.js in Vue.
  4. PapaParse - A library to parse CSV in Javascript.
  5. Bootstrap - A frontend framework.
  6. jQuery - A fast, small, and feature-rich JavaScript library, but mainly due to coming with Bootstrap for this tutorial.
  7. Proper.js - Position tooltips and popovers in modern web applications, come with Bootstrap.

You do not always need to use the CDN above, you can choose to download to your local folder or use other CDN servers.

To make browsers support the import keyword, we need to make sure the script is module type and please do note this is support by modern browsers only, if you want to use it in IE, you quite likely need to polyfill.

  <script type="module">      import { } from 'https://unpkg.com/vue-chartjs/dist/vue-chartjs.js';      //Other codes  </script>  

Then, we define a Vue component for the bar chart we want to create. The bar chart component will accept a chartdata property which is the data from the chart. We also define some chart properties here for e.g. responsive or not, maintain aspect ratio, chart legend, title and etc.

  Vue.component('barchart', {      extends: VueChartJs.Bar,      props: { chartdata: {          type: Object,          default: null      }},      mounted() {          this.renderChart(this.chartdata, {              responsive: true,               maintainAspectRatio: false,               legend: {                  position: 'top',              },              title: {                  display: true,                  text: 'Malaysia Covid 19 Daily New Cases using Vue and Chart.js'              }          });      }  });  

After having the bar chart component, we need to initialize a Vue and load the data from the external server. The this.loaded will temporary hide the chart if the data not yet loaded. After fetch the CSV data from MoH-Malaysia GitHub, we will use the Papa.parse to load the CSV with defined first row of CSV is the header. It will store in the response variable, we extract the daily new cases and date using Javascript map function. Then, we assign the values to chartdata.

  var vm = new Vue({      el: '#mychartjs',      data: () => ({           loaded: false,          chartdata: null      }),      async mounted() {          this.loaded = false;          const response = await fetch('https://raw.githubusercontent.com/MoH-Malaysia/covid19-public/main/epidemic/cases_malaysia.csv')              .then(response => response.text())              .then(v => Papa.parse(v, { header: true }))              .catch(err => console.log(err));            let cases = response.data.map(a => a.cases_new);          let date = response.data.map(a => a.date);          this.chartdata = {              labels: date,              datasets: [{ label: "Covid 19 cases", backgroundColor: "#f87979", data: cases }]          };          this.loaded = true;      }  })  

Finally, we need to define the HTML element for the Vue and chart. mychartjs is the main entrance for our Vue, barchart is our Vue component, v-if is not a property for bar chart component but use to show or hide the chart, and :chartdata is the property for component use to send data into bar chart component.

  <div class="container">      <div id="mychartjs">          <div class="row">              <barchart class="col-md-12" v-if="loaded" :chartdata="chartdata"></barchart>          </div>      </div>  </div>  

Below is the result of the page:

Bonus:
If you don't want to use the fetch method, you can use the promise method to fetch the data.

  //Reference: https://github.com/mholt/PapaParse/issues/752#issuecomment-567294386  const papaPromise = (url) => new Promise((resolve, reject) => {      Papa.parse(url, {          header: true,          download: true,          complete: function(results) {              resolve(results);          },          error: function(error) {              reject(error);          }      });  })    const response = await papaPromise("https://raw.githubusercontent.com/MoH-Malaysia/covid19-public/main/epidemic/cases_malaysia.csv")      .then(response => response)      .catch(err => console.log(err));  

Below is the complete code:

  <!doctype html>  <html lang="en">    <head>      <title>Malaysia Covid 19 Daily New Cases using Vue and Chart.js</title>      <!-- Required meta tags -->      <meta charset="utf-8">      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">        <!-- Bootstrap CSS -->      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">    </head>    <body>        <div class="container">          <div id="mychartjs">              <div class="row">                  <barchart class="col-md-12" v-if="loaded" :chartdata="chartdata"></barchart>              </div>          </div>      </div>              <!-- Optional JavaScript -->      <!-- jQuery first, then Popper.js, then Bootstrap JS -->      <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>      <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>      <script src="https://unpkg.com/vue@^2/dist/vue.js"></script>      <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>      <script src="https://unpkg.com/vue-chartjs/dist/vue-chartjs.js"></script>      <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.1/papaparse.min.js"></script>      <script type="module">          import { } from 'https://unpkg.com/vue-chartjs/dist/vue-chartjs.js';          Vue.component('barchart', {              extends: VueChartJs.Bar,              props: { chartdata: {                  type: Object,                  default: null              }},              mounted() {                  this.renderChart(this.chartdata, {                      responsive: true,                       maintainAspectRatio: false,                       legend: {                          position: 'top',                      },                      title: {                          display: true,                          text: 'Malaysia Covid 19 Daily New Cases using Vue and Chart.js'                      }                  });              }          });            //Reference: https://github.com/mholt/PapaParse/issues/752#issuecomment-567294386          const papaPromise = (url) => new Promise((resolve, reject) => {              Papa.parse(url, {                  header: true,                  download: true,                  complete: function(results) {                      resolve(results);                  },                  error: function(error) {                      reject(error);                  }              });          })            var vm = new Vue({              el: '#mychartjs',              data: () => ({                   loaded: false,                  chartdata: null              }),              async mounted() {                  this.loaded = false;                  const response = await fetch('https://raw.githubusercontent.com/MoH-Malaysia/covid19-public/main/epidemic/cases_malaysia.csv')                      .then(response => response.text())                      .then(v => Papa.parse(v, { header: true }))                      .catch(err => console.log(err));                    /*const response = await papaPromise("https://raw.githubusercontent.com/MoH-Malaysia/covid19-public/main/epidemic/cases_malaysia.csv")                      .then(response => response)                      .catch(err => console.log(err));*/                    let cases = response.data.map(a => a.cases_new);                  let date = response.data.map(a => a.date);                  this.chartdata = {                      labels: date,                      datasets: [{ label: "Covid 19 cases", backgroundColor: "#f87979", data: cases }]                  };                  this.loaded = true;              }          })      </script>    </body>  </html>  

This free site is ad-supported. Learn more