Creating a Visualization App Using the Google Charts API and AngularJS – Part 3
In the first and second parts of this series, we focused on AngularJS controllers and directives. In this part, we’ll focus on the two-way data binding feature of AngularJS.
Data Binding in AngularJS
Angular’s data binding allows changes to a model to be automatically reflected in the view, and vice versa. A detailed explanation of AngularJS data binding can be found here.
We will be adding a few features to our visualization app. First, we’ll add a drop down where we can select the type of graph. Let’s add a few charts in the drop down. Open up index.html
and add a select
element as shown below:
<select id="chartType"></select>
If we want, we can define the options for the dropdown in HTML only, but let’s do it the Angular way. Open up controllers.js
, and define the options as shown below.
$scope.chartTypes = [
{typeName: 'PieChart', typeValue: 'PieChart'},
{typeName: 'BarChart', typeValue: 'BarChart'},
{typeName: 'ScatterChart', typeValue: 'ScatterChart'},
{typeName: 'LineChart', typeValue: 'LineChart'}
];
$scope.chartType = $scope.chartTypes[0];
Now, controllers.js
looks like this:
'use strict';
/* Controllers */
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(function() {
angular.bootstrap(document.body, ['myApp']);
});
angular.module('myApp.controllers', []).
controller('MyCtrl1', ['$scope',function($scope) {
var data = google.visualization.arrayToDataTable([
['Year', 'Sales', 'Expenses'],
['2004', 1000, 400],
['2005', 1170, 460],
['2006', 660, 1120],
['2007', 1030, 540]
]);
var options = {
title: 'Company Performance'
};
var chart = {};
chart.data = data;
chart.options = options;
$scope.chartTypes = [
{typeName: 'LineChart', typeValue: '1'},
{typeName: 'BarChart', typeValue: '2'},
{typeName: 'ColumnChart', typeValue: '3'},
{typeName: 'PieChart', typeValue: '4'}
];
$scope.chartType = $scope.chartTypes[0];
$scope.chart = chart;
}])
.controller('MyCtrl2', [function() {
}]);
Now, we need to bind chartTypes
to the drop down. In AngularJS, we can bind options to a drop down using ngOptions. We also need to bind chartType
to the selected value in the drop down, and for that we use ngModel. So, add attributes named ng-options
and ng-model
to the drop down, as shown below.
<select id="chartType" ng-model="chartType" ng-options="c.typeName for c in chartTypes">
</select>
ng-options
iterates over the values in chartTypes
and binds each typeName
to the drop down. Before running the node server, we need to modify the ng-controller
value such that it is attached to the body
element. The resulting index.html
file is shown below.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My AngularJS App</title>
<link rel="stylesheet" href="css/app.css" />
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
</head>
<body ng-controller="MyCtrl1">
<div g-chart></div>
<select id="chartType" ng-model="chartType" ng-options="c.typeName for c in chartTypes">
</select>
<div>Angular seed app: v<span app-version></span></div>
<script src="lib/angular/angular.js"></script>
<script src="lib/angular/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
<script src="js/filters.js"></script>
<script src="js/directives.js"></script>
</body>
</html>
Next, start the node server using the following command.
node scripts/web-server.js
By navigating to http://localhost:8000/app/index.html
you should see the pre-populated drop down list.
Changing the Chart Type
We’re going to use ngChange
to render our chart based on the section in the drop down list. Inside controllers.js
define another $scope
variable as shown below.
$scope.selectType = function(type) {
$scope.chart.type = type.typeValue;
}
We also want to set the default chart type:
chart.type = $scope.chartTypes[0].typeValue;
After adding ng-change
to the select
element, it should look like this:
<select id="chartType" ng-change="selectType(chartType)" ng-model="chartType" ng-options="c.typeName for c in chartTypes">
</select>
Changing the chart type causes the $scope.chart.type
variable to be udpated. This change should be watched so that the chart changes accordingly. For that we have some thing called $scope.$watch
, which watches for a change in the $scope
. In directives.js
, wrap the link
callback, inside $scope.$watch
as shown below.
link: function($scope, elm, attrs) {
$scope.$watch('chart', function() {
var chart = new google.visualization.LineChart(elm[0]);
chart.draw($scope.chart.data, $scope.chart.options);
}, true);
}
This change causes every change to $scope.chart
to trigger the callback function. Inside the $scope.$watch
callback function, we need to check for $scope.chart.type
and create a chart object accordingly. Modify the gChart
directive in directives.js
as shown below.
.directive('gChart',function() {
return {
restrict: 'A',
link: function($scope, elm, attrs) {
$scope.$watch('chart', function() {
var type = $scope.chart.type;
var chart = '';
if (type == '1') {
chart = new google.visualization.LineChart(elm[0]);
} else if (type == '2') {
chart = new google.visualization.BarChart(elm[0]);
} else if (type == '3') {
chart = new google.visualization.ColumnChart(elm[0]);
} else if (type == '4') {
chart = new google.visualization.PieChart(elm[0]);
}
chart.draw($scope.chart.data, $scope.chart.options);
},true);
}
};
});
Now, when you select a different chart type from the drop down, the chart is updated.
Conclusion
In this tutorial, we implemented a drop down list and bound it using Angular’s two-way data binding. In our next tutorial, we’ll focus on adding some more features and bootstrapping the app to give it a feel good look. In the meantime, the code is available on GitHub, and a live demo is hosted on Heroku.