dev777
dev777

Reputation: 1019

How to draw a d3.js line chart using angularjs directives

How to use angular directives to load the d3.js graph using scope json data instead of using graph.html file.I had referred this urlurl.But unable to do it for line chart.

Can anyone please help me out regarding this issue ...

My graph.html:

function getDate(d) {
 var dt = new Date(d.date);
 dt.setHours(0);
 dt.setMinutes(0);
 dt.setSeconds(0);
 dt.setMilliseconds(0);
 return dt;
 }

function showData(obj, d) {
 var coord = d3.mouse(obj);
 var infobox = d3.select(".infobox");
 // now we just position the infobox roughly where our mouse is
 infobox.style("left", (coord[0] + 100) + "px" );
 infobox.style("top", (coord[1] - 175) + "px");
 $(".infobox").html(d);
 $(".infobox").show();
 }

function hideData() {
 $(".infobox").hide();
 }

var drawChart = function(data) {
 // define dimensions of graph
 var m = [10, 20, 10, 50]; // margins
 var w = 250 - m[1] - m[3]; // width
 var h = 100 - m[0] - m[2]; // height

data.sort(function(a, b) {
 var d1 = getDate(a);
 var d2 = getDate(b);
 if (d1 == d2) return 0;
 if (d1 > d2) return 1;
 return -1;
 });


 var minDate = getDate(data[0]),
 maxDate = getDate(data[data.length-1]);

 var x = d3.time.scale().domain([minDate, maxDate]).range([0, w]);


 var y = d3.scale.linear().domain([0, d3.max(data, function(d) { return d.trendingValue; } )]).range([h, 0]);


 var line = d3.svg.line()

 .x(function(d, i) {

 return x(getDate(d)); //x(i);
 })
 .y(function(d) {

 return y(d.trendingValue);
 });

 function xx(e) { return x(getDate(e)); };
 function yy(e) { return y(e.trendingValue); };



 var graph = d3.select("#chart").append("svg:svg")
 .attr("width", w + m[1] + m[3])
 .attr("height", h + m[0] + m[2])
 .append("svg:g")
 .attr("transform", "translate(" + m[3] + "," + m[0] + ")");


 var xAxis = d3.svg.axis().scale(x).ticks(d3.time.months, 1).tickSize(-h).tickSubdivide(true);

 var yAxisLeft = d3.svg.axis().scale(y).ticks(10).orient("left"); //.tickFormat(formalLabel);

 graph
 .selectAll("circle")
 .data(data)
 .enter().append("circle")
 .attr("fill", "steelblue")
 .attr("r", 5)
 .attr("cx", xx)
 .attr("cy", yy)
 .on("mouseover", function(d) { showData(this, d.trendingValue);})
 .on("mouseout", function(){ hideData();});

 graph.append("svg:path").attr("d", line(data));



 $("#chart").append("<div class='infobox' style='display:none;'>Test</div>");
 }

My directive:(which I had tried but unable to draw a graph)

angular.module( 'chart').directive( 'crD3Bars', [
  function () {
    return {
      restrict: 'E',
      scope: {
        data: '='
      },
      link: function (scope, element) {
        function getDate(d) {
 var dt = new Date(d.date);
 dt.setHours(0);
 dt.setMinutes(0);
 dt.setSeconds(0);
 dt.setMilliseconds(0);
 return dt;
 }

function showData(obj, d) {
 var coord = d3.mouse(obj);
 var infobox = d3.select(".infobox");
 // now we just position the infobox roughly where our mouse is
 infobox.style("left", (coord[0] + 100) + "px" );
 infobox.style("top", (coord[1] - 175) + "px");
 $(".infobox").html(d);
 $(".infobox").show();
 }

function hideData() {
 $(".infobox").hide();
 }

var drawChart = function(data) {
 // define dimensions of graph
 var m = [10, 20, 10, 50]; // margins
 var w = 250 - m[1] - m[3]; // width
 var h = 100 - m[0] - m[2]; // height

data.sort(function(a, b) {
 var d1 = getDate(a);
 var d2 = getDate(b);
 if (d1 == d2) return 0;
 if (d1 > d2) return 1;
 return -1;
 });


 var minDate = getDate(data[0]),
 maxDate = getDate(data[data.length-1]);

 var x = d3.time.scale().domain([minDate, maxDate]).range([0, w]);


 var y = d3.scale.linear().domain([0, d3.max(data, function(d) { return d.trendingValue; } )]).range([h, 0]);


 var line = d3.svg.line()

 .x(function(d, i) {

 return x(getDate(d)); //x(i);
 })
 .y(function(d) {

 return y(d.trendingValue);
 });

 function xx(e) { return x(getDate(e)); };
 function yy(e) { return y(e.trendingValue); };



 var graph = d3.select("#chart").append("svg:svg")
 .attr("width", w + m[1] + m[3])
 .attr("height", h + m[0] + m[2])
 .append("svg:g")
 .attr("transform", "translate(" + m[3] + "," + m[0] + ")");


 var xAxis = d3.svg.axis().scale(x).ticks(d3.time.months, 1).tickSize(-h).tickSubdivide(true);

 var yAxisLeft = d3.svg.axis().scale(y).ticks(10).orient("left"); //.tickFormat(formalLabel);

 graph
 .selectAll("circle")
 .data(data)
 .enter().append("circle")
 .attr("fill", "steelblue")
 .attr("r", 5)
 .attr("cx", xx)
 .attr("cy", yy)
 .on("mouseover", function(d) { showData(this, d.trendingValue);})
 .on("mouseout", function(){ hideData();});

 graph.append("svg:path").attr("d", line(data));



 $("#graphDiv3").append("<div class='infobox' style='display:none;'>Test</div>");
 }
drawchart(data);
        }
    };
  }
]);

Upvotes: 0

Views: 3112

Answers (1)

Mark
Mark

Reputation: 108512

Instead of mashing up two blocks of code and hoping it works, I'd recommend you follow some simple angular tutorials to get a better grasp of the basics. Also, some simple debugging would have gone a long way here.

  1. You do not declare your module.
  2. You do not seem to pass in your data anywhere (like in a controller which also doesn't exist).
  3. The function is drawChart, you are calling drawchart
  4. In your directive, you select a div with id of chart, this doesn't exist. Since it's a directive and they act on elements use d3.select(element[0])

All that said once you work through these relatively simple mistakes, you get some working code:

var myAppModule = angular.module('chart', []);

angular.module('chart').controller('chartCtrl', function ($scope) {
  
  $scope.myData =  [{
        "date": "2015-10-01",
        "trendingValue": "244"
    },
    {
        "date": "2015-07-01",
        "trendingValue": "0"
    },
    {
        "date": "2015-06-01",
        "trendingValue": "117"
    },
    {
        "date": "2015-05-01",
        "trendingValue": "5353"
    },
    {
        "date": "2015-04-01",
        "trendingValue": "11159"
    },
    {
        "date": "2015-03-01",
        "trendingValue": "7511"
    },
    {
        "date": "2015-02-01",
        "trendingValue": "6906"
    },
    {
        "date": "2015-01-01",
        "trendingValue": "10816"
    },
    {
        "date": "2014-12-01",
        "trendingValue": "3481"
    },
    {
        "date": "2014-11-01",
        "trendingValue": "1619"
    },
    {
        "date": "2014-10-01",
        "trendingValue": "4084"
    },
    {
        "date": "2014-09-01",
        "trendingValue": "1114"
    }];
});

angular.module('chart').directive('crD3Bars', [
  function() {
    return {
      restrict: 'E',
      scope: {
        data: '='
      },
      link: function(scope, element) {
        
        function getDate(d) {
          var dt = new Date(d.date);
          dt.setHours(0);
          dt.setMinutes(0);
          dt.setSeconds(0);
          dt.setMilliseconds(0);
          return dt;
        }

        function showData(obj, d) {
          var coord = d3.mouse(obj);
          var infobox = d3.select(".infobox");
          // now we just position the infobox roughly where our mouse is
          infobox.style("left", (coord[0] + 100) + "px");
          infobox.style("top", (coord[1] - 175) + "px");
          $(".infobox").html(d);
          $(".infobox").show();
        }

        function hideData() {
          $(".infobox").hide();
        }

        var drawChart = function(data) {
          
          // define dimensions of graph
          var m = [10, 20, 10, 50]; // margins
          var w = 250 - m[1] - m[3]; // width
          var h = 100 - m[0] - m[2]; // height

          data.sort(function(a, b) {
            var d1 = getDate(a);
            var d2 = getDate(b);
            if (d1 == d2) return 0;
            if (d1 > d2) return 1;
            return -1;
          });


          var minDate = getDate(data[0]),
            maxDate = getDate(data[data.length - 1]);

          var x = d3.time.scale().domain([minDate, maxDate]).range([0, w]);


          var y = d3.scale.linear().domain([0, d3.max(data, function(d) {
            return d.trendingValue;
          })]).range([h, 0]);


          var line = d3.svg.line()

          .x(function(d, i) {

              return x(getDate(d)); //x(i);
            })
            .y(function(d) {

              return y(d.trendingValue);
            });

          function xx(e) {
            return x(getDate(e));
          }

          function yy(e) {
            return y(e.trendingValue);
          }

          var graph = d3.select(element[0]).append("svg:svg")
            .attr("width", w + m[1] + m[3])
            .attr("height", h + m[0] + m[2])
            .append("svg:g")
            .attr("transform", "translate(" + m[3] + "," + m[0] + ")");


          var xAxis = d3.svg.axis().scale(x).ticks(d3.time.months, 1).tickSize(-h).tickSubdivide(true);

          var yAxisLeft = d3.svg.axis().scale(y).ticks(10).orient("left"); //.tickFormat(formalLabel);

          graph
            .selectAll("circle")
            .data(data)
            .enter().append("circle")
            .attr("fill", "steelblue")
            .attr("r", 5)
            .attr("cx", xx)
            .attr("cy", yy)
            .on("mouseover", function(d) {
              showData(this, d.trendingValue);
            })
            .on("mouseout", function() {
              hideData();
            });

          graph.append("svg:path").attr("d", line(data));

          $("#graphDiv3").append("<div class='infobox' style='display:none;'>Test</div>");
        };

        drawChart(scope.data);
      }
    };
  }
]);
<!DOCTYPE html>
<html ng-app="chart">

  <head>
    <script data-require="[email protected]" data-semver="1.4.8" src="https://code.angularjs.org/1.4.8/angular.js"></script>
    <script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
    <script data-require="[email protected]" data-semver="2.1.4" src="https://code.jquery.com/jquery-2.1.4.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <div id="graphDiv3" ng-controller="chartCtrl">
      <cr-d3-bars data="myData"></cr-d3-bars>
    </div>
  </body>

</html>

Upvotes: 2

Related Questions