Build a live graph with Ember.js
You will need Node and npm installed on your machine.
Introduction
In this post, we will build a simple interactive graph with Ember.js. With this, a user can have a better understanding of the data by hovering on a point and seeing more information using the hovering facility as depicted in the image below:
Prerequisites
It is important that you have Node.js and npm installed on your machine. Learn how to install Node.js and npm here. A quick run-down of the core technologies we will be using include:
- Ember.js: an open source JavaScript web framework for creating scalable single-page web applications.
- Pusher: a Node.js client to interact with the Pusher REST API.
- Express: Node utility for handling HTTP requests via routes.
Getting started
To get started with an Ember application, it is recommended to use Ember CLI tool as this will enable you to conveniently craft a new app with a single command. You can install it with npm, open your terminal and type this command:
npm install -g ember-cli
The Ember CLI will give us access to the ember
command that will be used to set up our project easily.
Creating the application
We now have access to the ember new
command that can be used to create our application. Open up the terminal on your machine and run a command that will create an application named ember-realtime-graph
in your project directory:
ember new ember-realtime-graph
Next, change directory into the newly created project and start the development server:
// change directory
cd ember-realtime-graph
// start the development server
ember serve
This will start the development server on http://localhost:4200. Open your favorite browser and navigate to that URL, you should see a default welcome page by Ember.js as shown below:
Install server dependencies
Run the following command to install the dependencies required for this project using:
npm install --save pusher pusher-js chart.js
npm install --save dotenv express
ember install ember-browserify
Setting up a Pusher application
Head over to Pusher and sign up for a free account.
Create a new app by selecting Channels apps on the sidebar and clicking Create Channels app button on the bottom of the sidebar:
Configure an app by providing basic information requested in the form presented. You can also choose the environment you intend to integrate Pusher with to be provided with some boilerplate code:
You can retrieve your keys from the App Keys tab:
Setting the environment variables
Create a .env
file in the root directory of your application and add your application credentials as obtained from your Pusher dashboard as follows:
PUSHER_APP_ID=YOUR_APP_ID
PUSHER_APP_KEY=YOUR_APP_KEY
PUSHER_APP_SECRET=YOUR_APP_SECRET_KEY
PUSHER_APP_CLUSTER=CLUSTER
We will make use of the variables specified in the above snippet later in our project. Ensure that you replace YOUR_APP_ID
, YOUR_APP_KEY
, YOUR_APP_SECRET_KEY
and CLUSTER
placeholders with the appropriate credentials.
Setting up the server
To properly demonstrate realtime update of our graph, we’ll make use of an existing dummy data of stock trades and price variations. For our Ember application to keep receiving this data at a specified regular interval, let’s quickly set up a simple server.
Create an app.js
file in the root directory of your application and add the following code snippet to it to set up the server:
// app.js
const express = require('express');
const Pusher = require('pusher');
require('dotenv').config();
const stockData = require('./stock.json')
const app = express();
const pusher = new Pusher({
appId: process.env.PUSHER_APP_ID,
key: process.env.PUSHER_APP_KEY,
secret: process.env.PUSHER_APP_SECRET,
cluster: process.env.PUSHER_APP_CLUSTER,
encrypted: true
});
let i = 0;
setInterval( () => {
const GOOG = stockData[1]['Trades'][i];
pusher.trigger('trade', 'stock', GOOG)
i++
}, 2000);
app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'), () => {
console.log("Listening on port " + app.get('port'));
})
```
We loaded the required middlewares for the Express server and then imported dummy data for stock trades. You can download this data [here](https://github.com/yemiwebby/ember-realtime-graph/blob/master/stock.json). Once you are done, create a new file named `stock.json` in the root directory of the application and save the downloaded content in it.
Next, we configured Pusher using the credentials we added to our environment variables earlier. And finally, to allow our client receive realtime payloads, we emitted the `stockData` payload on every 2 seconds for our client to subscribe to.
Open another terminal and run the command below to start the server on http://localhost:3000:
```
node app.js
```
This will log a message to the console as shown by the image below:
![ember-realtime-graph-server](//images.ctfassets.net/1es3ne0caaid/5YZBY3LYSAMSkiqkEAiS8G/7a360584de801669039b57b7e38b33e3/ember-realtime-graph-server.png)
## Generate the chart component
Ember supports the usage and sharing of UI elements on multiple pages. So, we’ll use the component approach and generate one for our application.
Run the command below:
```
ember generate component realtime-graph
```
The command above will generate a JavaScript component file `./app/components/realtime-graph.js` and a Handlebars template that defines the markup for the component’s UI.
## Initialize the chart
Next, we’ll initialize the chart to display the stock data to users in realtime. Open the newly generated `./app/components/realtime-graph.js` and update it with:
``` javascript
// ./app/components/realtime-graph.js
import Component from '@ember/component';
import Pusher from 'npm:pusher-js';
import Chart from 'npm:chart.js';
export default Component.extend({
init() {
this._super(...arguments);
var chart;
initializeChart();
function initializeChart() {
var ctx = document.getElementById('chart').getContext('2d');
const data = {
labels: [],
datasets: [{
label: "My First dataset",
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
fill: false,
data: [],
}]
};
chart = new Chart(ctx, {
type: 'line',
data: data,
options: {
responsive: true,
title: {
display: true,
text: 'Chart.js Line Chart'
},
tooltips: {
mode: 'index',
intersect: false
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [
{
display: true,
scaleLabel: {
display: true,
labelString: 'Time '
}
}
],
yAxes: [
{
display: true,
scaleLabel: {
display: true,
labelString: 'Price'
},
ticks: {
min: 504,
max: 507
}
}
]
}
}
})
}
// we will update the chart here
}
});
```
The essence of what we executed here is to initialize the chart with a method named `intializeChart()`. We used it to define a chart and described the kind of data that it should expect, the label, including the colors. We’ll update it with data later in the tutorial.
## Update the app template
Update the application template to get rid of the default welcome page and show our chart in its place. Open the `./app/templates/application.hbs` file and paste the code below in it:
``` html
{{!-- ./app/templates/application.hbs --}}
<canvas id="chart"></canvas>
{{#realtime-graph}}{{/realtime-graph}}
{{outlet}}
```
Now if you stop the Ember development server by typing `Ctrl + c` in the terminal and restart it with `ember serve`, you will see a blank graph as shown in the image below:
![ember-realtime-graph-homepage](//images.ctfassets.net/1es3ne0caaid/27hId3SqJm4mqiCyg6gi0e/21a3d9ed8aadc967ea85734594c04b14/ember-realtime-graph-homepage.png)
This is because we have not started updating our graph with the data sent in from the server. We’ll change that in the next section.
## Update the chart
Our graph requires constant data from the server in order to be displayed. Open `./app/components/realtime-graph.js` and add the code below immediately after the `initializeChart()` method:
``` javascript
// ./app/components/realtime-graph.js
import Component from '@ember/component';
import Pusher from 'npm:pusher-js';
export default Component.extend({
init() {
...
const pusher = new Pusher('YOUR_APP_KEY', { // update your APP_KEY
cluster: 'CLUSTER',
encrypted: true
})
const channel = pusher.subscribe('trade');
channel.bind('stock', data => {
chart.data.labels.push(data.Timestamp.split(' ')[1].split('.')[0]);
chart.data.datasets[0].data.push(data.Price);
chart.update();
})
}
});
```
Here, we initialized Pusher and subscribed to the `trade` channel in order to update the chart every single time data comes in from the server. Do not forget to replace the `YOUR_APP_KEY` and `CLUSTER` placeholder with the appropriate credentials.
## Testing the application
Stop the Ember development server if it is currently running by typing `Ctrl + C` in the terminal and restart it with `ember serve`. In addition, don’t forget to also run `node app.js` from another terminal to start the server in case you haven’t done that. Next, open http://localhost:4200 to test the application.
![ember-realtime-graph-final-homepage](//images.ctfassets.net/1es3ne0caaid/6u3iPDalHOGIwWEKqcsymA/5a67085df6e34216f492acf7d09ff2b1/ember-realtime-graph-final-homepage.png)
## Conclusion
Interactivity becomes more powerful when you allow users to select points or series in a chart and have a summary of the relevant data appears for them to see. This helps to improve clean looking visualizations of data on a chart. You can easily build similar applications by using any charting tool of your choice.
The complete source code can be found on [GitHub](https://github.com/yemiwebby/ember-realtime-graph).
26 June 2018
by Christian Nwamba