Chart.js Example with Dynamic Dataset
Tags: javascript, tutorial, webdev, beginners
Published: 2019-09-25 14:23:56

---
title: Chart.js Example with Dynamic Dataset
published: true
description: Chart.js Example with Dynamic Data
tags: javascript,tutorial,webdev,beginners
cover_image: https://media.graphcms.com/iy4SJuZSlqNwp9Yk8ApN
---

I've already covered building a static dashboard with [Cube.js](https://github.com/cube-js/cube.js) and Chart.js in [this tutorial](https://cube.dev/blog/node-express-analytics-dashboard-with-cubejs/). Now, I’m going to show you how to dynamically change the underlying chart’s data based on the user’s input. We’ll let the user pick a date range and based on that, reload the chart. When a user picks a new set of dates, a new request will be sent to the Cube.js server. The Cube.js server will generate new SQL code, execute it against the database, and send the result back to the client. And finally, the client re-renders a chart with the new data.

Here is a Codesandbox demo of what we are going to build. You can click "Open in Editor" to check the source code.

{% codesandbox chartjs-dynamic-data-example-yebll %}

## Setting up a Backend

We are going to use our sample e-commerce Postgres dataset. Use the following commands to download it and import it into the `ecom` database.

```bash
$ curl http://cube.dev/downloads/ecom-dump.sql > ecom-dump.sql
$ createdb ecom
$ psql --dbname ecom -f ecom-dump.sql
```

Next, install Cube.js CLI if you don’t have it already and generate a new application.

```bash
$ npm install -g cubejs-cli
$ cubejs create chartjs-dynamic-data -d postgres
```

Cube.js uses environment variables for configuration. To configure the connection to our database, we need to specify the DB type and name. In the Cube.js project folder, replace the contents of the .env file with the following:

```bash
CUBEJS_API_SECRET=SECRET
CUBEJS_DB_TYPE=postgres
CUBEJS_DB_NAME=ecom
```

Now, start the development server and open the [localhost:4000](https://localhost:4000) in your browser.

```bash
$ npm run dev
```

You can generate a schema for the tables in the `ecom` database under the Schema tab. We’re going to use data from only one table—`orders`. Once you generate this schema, you can play around with the data in the Explore section.

![](https://media.graphcms.com/6qLZzSIzQxWEMI4dxIDr)

There are multiple ways to deploy Cube.js: Docker, serverless, and Heroku. You can read about [all of them here](https://cube.dev/docs/deployment). In this tutorial, we are going to use the Cube.js application deployed to Heroku at [https://cubejs-ecom.herokuapp.com/cubejs-api/v1](https://cubejs-ecom.herokuapp.com/cubejs-api/v1).

## Simple Chart

We’ll build our frontend on the Codesandox for simplicity. It will load the data from the Cube.js backend deployed on Heroku. You can check out the final source code and the demo app here. Feel free to fork it and play around.

We are using the Vanilla template from Codesanbox and are not going to add any framework, such as React or Vue, to keep things simple. The first step is to include the Cube.js client and Chart.js libraries. Insert the following code inside the `<head>` tag.

```html
<script src="https://unpkg.com/@cubejs-client/core@0.10.16/dist/cubejs-client-core.umd.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
```

To initialize the Cube.js client, you need to pass an API URL along with the Secret.

```javascript
const cubejsApi = cubejs(
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.K9PiJkjegbhnw4Ca5pPlkTmZihoOm42w8bja9Qs2qJg",
  { apiUrl: "https://cubejs-ecom.herokuapp.com/cubejs-api/v1" }
);
```

Once the client is initialized, we can request data from the backend and visualize it. The `load` function accepts a query, which is a plain javascript object, and returns a promise. You can learn more about the [query format here](https://cube.dev/docs/query-format#top).

```javascript
cubejsApi
    .load({
      measures: ["Orders.count"],
      timeDimensions: [
        {
          dimension: "Orders.createdAt",
          granularity: `day`,
          dateRange: [`08/01/2019`,`09/01/2019`]
        }
      ]
    })
    .then(resultSet => {
      new Chart(document.getElementById("chart"), {
        type: "line",
        options: options,
        data: chartJsData(resultSet)
      });
    });
```

We are loading `Orders.count`, which is grouped by the created day to plot as a line chart. To make this code work, we need to make a couple of things. First, add the `<canvas>` tag to the inside of your html `<body>`.

```html
<canvas id="chart-canvas"></canvas>
```

Next, we need to define a `chartJsData` function, which should accept a [resultSet](https://cube.dev/docs/@cubejs-client-core#result-set) returned from Cube.js and format it for Chart.js.

```javascript
var chartJsData = function(resultSet) {
  return {
    datasets: [
      {
        label: "Orders Count",
        data: resultSet.chartPivot().map(function(r) {
          return r["Orders.count"];
        }),
        backgroundColor: "rgb(255, 99, 132)"
      }
    ],
    labels: resultSet.categories().map(function(c) {
      return c.x;
    })
  };
};
```

Lastly, we are declaring some additional Chart.js options for nice axes formatting.

```javascript
var options = {
  scales: {
    xAxes: [
      {
        type: "time",
        time: {
          displayFormats: {
            hour: "MMM DD"
          },
          tooltipFormat: "MMM D"
        }
      }
    ],
    yAxes: [
      {
        ticks: {
          beginAtZero: true
        }
      }
    ]
  }
};
```

That is all we need to load a static line chart. Next, we’re going to add a date range picker and load data dynamically based on the date range selected by the user.

## Dynamic Data

Add Jquery, Date Range Picker, and Moment.js libraries to your `<head>` tag.

```html
<script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css"/>
```

Next, let’s wrap the code to render a chart into the `drawChart` function, which is going to accept two arguments: start date and end date.

```javascript
var drawChart = function(startDate, endDate) {
  cubejsApi
    .load({
      measures: ["Orders.count"],
      timeDimensions: [
        {
          dimension: "Orders.createdAt",
          granularity: `day`,
          dateRange: [startDate, endDate]
        }
      ]
    })
    .then(resultSet => {
      if (window.chart) {
        window.chart.data = data;
        window.chart.update();
      } else {
        window.chart = new Chart(document.getElementById("chart-canvas"), 
        {
          type: "line",
          options: options,
          data: data
        });
      }
    });
};
```

Besides making the `dateRange` dynamic, we’re also saving the current chart into `windows.chart` so we can update it later when we need to re-render the chart. 

Finally, we can add an input to our html body and make it a date range picker:

```html
<input name="dates" />
```

```javascript
const START_DATE = "08/01/2019";
const END_DATE = "09/01/2019";

$('input[name="dates"]').daterangepicker(
  {
    startDate: START_DATE,
    endDate: END_DATE
  },
  function(start, end) {
    drawChart(start, end);
  }
);
drawChart(START_DATE, END_DATE);
```

That is it! Now we have a fully working dynamic and interactive chart. You can select different dates from the date picker and see how the chart is changing. 

{% codesandbox chartjs-dynamic-data-example-yebll %}

If you have any questions about this tutorial or about Cube.js in general—feel free to ping me in the [Slack Cube.js Community](https://slack.cube.dev/).