Subscribe via RSS Feed

D3.js in Angular.js Directive – a relief from D3 svg code in HTML Page

July 2, 2013 12 Comments

We have came through D3.js coding for Graph generation in our projects. To me personally, this coding is somewhat complex for startup programmers.

Recently I am going through learning Angular.js and Angular Directive.  So I had a thought to introduce an angular directive which will wrap the complex functionality of D3.js.

So here is the result – this post – creating a bar chart through Angular Directive with the help of D3.js.

I have learned the D3.js code from - http://bl.ocks.org/mbostock/3885304

Also here is our previous documentation on making the Angular Directive.

First – the Bar Chart Picture -

AngularD3BarGraph

Now the Commented code snippet in HTML -

<body>
   <div id="d3bar" angulard3-bar-graph datajson="'sample.json'" 
                   xaxis-name = "'Year'" 
                   xaxis-pos = "905"  
                   yaxis-name = "'Frequency'" 
                   yaxis-pos = "6" 
                   d3-format= "'.0%'" >
   <!-- angular directive is angulard3-bar-graph -->
   <!-- directive variables are xaxis-name,yaxis-name,xaxis-pos,yaxis-pos,y axis data format(d3-format)
        and finally the datajson variable which is holding the external data source -->
   </div>
</body>

And below is

Angular directive which wrapped d3.js code for Bar Graph

javascriptnosqlbook

angular.module('AngularD3BarGraph', []) // Angular Module Name
    .directive('angulard3BarGraph', function () { // Angular Directive
        return {
            restrict: 'A', // Directive Scope is Attribute
            scope: {
                datajson: '=',
                xaxisName: '=',
                xaxisPos: '=',
                yaxisName: '=',
                yaxisPos: '=',
                d3Format: '='
                // All the Angular Directive Vaiables used as d3.js parameters
            },
            link: function (scope, elem, attrs) {
                // The d3.js code for generation of bar graph. further reading should be done from http://d3js.org/
                var margin = {top: 20, right: 20, bottom: 30, left: 40},
                    width = 960 - margin.left - margin.right,
                    height = 500 - margin.top - margin.bottom;

                var formatPercent = d3.format(scope.d3Format); // formatting via angular variable

                var x = d3.scale.ordinal()
                       .rangeRoundBands([0, width], .1);

               var y = d3.scale.linear()
                       .range([height, 0]);

               var xAxis = d3.svg.axis()
                       .scale(x)
                       .orient("bottom");

               var yAxis = d3.svg.axis()
                       .scale(y)
                       .orient("left")
                       .tickFormat(formatPercent);

               var svg = d3.select("#"+elem[0].id).append("svg") // selecting the DOM element by d3.js 
                                                                 // - getting from Angular context   
                   .attr("width", width + margin.left + margin.right)
                   .attr("height", height + margin.top + margin.bottom)
                   .append("g")
                       .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

              d3.json(scope.datajson, function(error, data) { // external data filename- angular directive variable
                  if (error) return console.warn(error);

                  x.domain(data.map(function(d) { return d.letter; }));
                  y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

                  svg.append("g")
                      .attr("class", "x axis")
                      .attr("transform", "translate(0," + height + ")")
                      .call(xAxis)
                      .append("text")
                          .attr("x", scope.xaxisPos)
                          .attr("dx", ".71em")
                          .style("text-anchor", "end")
                          .text(scope.xaxisName);
                  // x axis legend setting from angular variables
                  svg.append("g")
                      .attr("class", "y axis")
                      .call(yAxis)
                      .append("text")
                          .attr("transform", "rotate(-90)")
                          .attr("y", scope.yaxisPos)
                          .attr("dy", ".71em")
                          .style("text-anchor", "end")
                          .text(scope.yaxisName);
                  // y axis legend setting from angular variables
                  svg.selectAll(".bar")
                      .data(data)
                      .enter().append("rect")
                      .attr("class", "bar")
                      .attr("x", function(d) { return x(d.letter); })
                      .attr("width", x.rangeBand())
                      .attr("y", function(d) { return y(d.frequency); })
                      .attr("height", function(d) { return height - y(d.frequency); });
                  });
              }
           }
       });

So that is all for now.

Code can be downloaded from Github.

As we are learning d3.js, we will explore wrapping more of the functional code in angular directive in our later works.

Thanks for reading…  Also if you find this article helpful, you can connect us in Google+ and Twitter.

Want to get blog updates? Subscribe here