Building a Visualization App with Google Charts API and AngularJS – Part 2

Share this article

The first part of this tutorial focused on the use of AngularJS controllers and the use of $scope. This part of the tutorial will focus on Angular directives their relation to $scope. We’ll start exactly from where we left off in the first article.

AngularJS Directives

Directives are another interesting and important aspect of AngularJS. Directives are custom tags or attributes, which enhance the abilities of HTML. For example, consider a simple input element:

<input type="text" />

Now, suppose we wrote a directive for a datepicker and want to apply that to the above input element. We would apply it in the following fashion.

<input type="text" datepicker />

In the first tutorial, we collected our chart data, along with the chart options, and bound the data to a div from the controller. However, directives provide a better and more organized way to accomplish the same thing. Before writing our own directive, let’s have a look at a directive which is already in the Angular seed project. Open up app/js/directives.js and find the following code:

'use strict';

/* Directives */

angular.module('myApp.directives', []).
  directive('appVersion', ['version', function(version) {
    return function($scope, elm, attrs) {
      elm.text(version);
    };
  }]);

This example defines a directive named appVersion. Note that when we add this directive, whose name is written in CamelCase), as a custom tag to an element, the casing is converted to SnakeCase.

In this directive, we are assigning a version number to the element to which the directive is attached. But, where is this version number coming from? Well, we have something called an AngularJS service, and that is where the version comes from. Open up app/js/services.js and you can see the version number defined there.

'use strict';

/* Services */

// In this case it is a simple value service.
angular.module('myApp.services', []).
  value('version', '0.1');

In order to access the value of version in the directive, it is injected into the directive using the following code:

directive('appVersion', ['version', function(version) {

Then, it is assigned to the element using elm.text(version);.

Now, simply add a div to index.html, as shown below. This attaches the appVersion directive to a span element.

<div >Angular seed app: v<span app-version></span></div>

To run the application, issue the following command from a terminal window.

node scripts/web-server.js

Next, point your browser to http://localhost:8000/app/index.html. The version defined in services.js should be displayed on the page. Now, let’s create a new directive for displaying our chart.

Creating an AngularJS Directive

Let’s create a new directive named gChart in directives.js:

'use strict';

/* Directives */

angular.module('myApp.directives', []).
directive('appVersion', ['version',
  function (version) {
    return function ($scope, elm, attrs) {
      elm.text(version);
    };
  }
])
  .directive('gChart', function () {
    return function ($scope, elm, attrs) {
    };
  });

In the previous article, we bound the data in the controller itself. This time we’re goint to pass the data using $scope and bind it inside the directive. The modified code is shown below.

'use strict';

/* Directives */

angular.module('myApp.directives', []).
directive('appVersion', ['version',
  function (version) {
    return function ($scope, elm, attrs) {
      elm.text(version);
    };
  }
])
  .directive('gChart', function () {
    return function ($scope, elm, attrs) {
      var chart = new google.visualization.LineChart(document.getElementById('chartdiv'));

      chart.draw($scope.chart.data, $scope.chart.options);
    };
  });

Inside controllers.js, remove the last two lines where we bind data to a div, and instead save the chart data and options inside $scope. The file should now look 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.chart = chart;
  }])
  .controller('MyCtrl2', [function() {
  }]);

Now, add the gChart directive to the div in index.html as shown below:

<div ng-controller="MyCtrl1" id="chartdiv" g-chart></div>

Next, run the app and you should be able to see the graph.

At this point, we are using controllers to take care of the application logic. Data is assigned to the view via $scope, and DOM manipulation is handled using the directive.

More Information on Directives

When creating a directive, we can specify how we want to use the directive. For example, a directive can be used as a class, an attribute, or a tag. In this tutorial, we’ll be using our directive as an attribute. Hence, we can explicitly declare that using restrict : A. A minimalistic directive that uses this approach is shown below.

.directive('gChart', function() {
  return {
    restrict: 'A',
    link: function($scope, elm, attrs) {
      var chart = new google.visualization.LineChart(document.getElementById('chartdiv'));

      chart.draw($scope.chart.data, $scope.chart.options);
    }
  };
});

We can also remove the hard coded chartDiv from the directive code and access it using the elm argument, as shown below.

.directive('gChart', function() {
  return {
    restrict: 'A',
    link: function($scope, elm, attrs) {
      var chart = new google.visualization.LineChart(elm[0]);

      chart.draw($scope.chart.data, $scope.chart.options);
    }
  };
});

Conclusion

In this tutorial, we focused on the use of directives. In the next part of this tutorial, we will dig deeper into the two-way binding features of AngularJS, and incorporate them into our existing app. In the meantime, all of the code from this article is available on GitHub.

Jay is a Software Engineer and Writer. He blogs occasionally at Code Handbook and Tech Illumination.

ChartsdirectivesGoogle Tutorials & Articles
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week