D3 in AngularJS Application

I am trying to create my first application using AngularJS. It looks neat, but there is a lot of abstraction, and I'm just wondering if anyone has any tips on the most idiomatic way to use the angular methodology to update visual images created with d3js.

Thank you

+42
angularjs
Jun 21 2018-12-12T00:
source share
5 answers

To make angular and other frameworks good, you need to wrap the "other" frameworks using directives.

http://docs.angularjs.org/guide/directive

What you want to do is tell angular when the data has been updated by "other" frames. If angular does not need to know, then your task will be easier.

Here is an example that works with SVG, its awesome

http://sullerandras.github.com/SVG-Sequence-Diagram/

Here is an example that includes TinyMCE

http://jsfiddle.net/programmieraffe/kjsEV/

+34
Jun 21 '12 at 18:26
source share

Please also check out the article by Brian Ford (AngularJS internship), where he details the integration of AngluarJS with D3.

http://briantford.com/blog/angular-d3.html

+44
Aug 17 '12 at 4:05
source share

It is also possible to insert AngularJS descriptor syntax directly into d3-generated elements:

var containerDiv = d3.select(targetCSSSelectorForADiv); var svgG = containerDiv .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") svgG.selectAll(".tempclass").data(scope.circles).enter() .append("circle") .attr("class", "tempclass") .attr("cx", function (d, i) { return "{{circles[" + i + "].cx}}" }) .attr("cy", function (d, i) { return "{{circles[" + i + "].cy}}" }) .attr("r", function (d, i) { return "{{circles[" + i + "].radius}}" }) .attr("ng-style", function (d, i) { return "{fill: circles[" + i + "].circolor" + ", opacity: circles[" + i + "].opa" + ", 'stroke-width': 4*circles[" + i + "].opa" + ", stroke: 'red' }"; }); 

Note the following: the scope is an angular object object passed from the directive to the rendering function. Setting the element style to the expression "{...}} will not work, so I use the attribute" ng-style "here.

However, there is one more trick: you need to tell angular to look at the dynamically generated DOM elements and bind the data binding, now I know two ways to do this:

 //the target div is the one with the angular ng-controller attribute //this you can call at the end of the d3 rendering call from within the render function angular.bootstrap(document.getElementById("d3ContainerDivID"), ['d3App']); 

Another way:

 //and this could be called from the directive that triggered the rendering or //some other place that could have the angular $compile service injected $compile(document.getElementById("d3ContainerDivID"))(scope); 

Now you can change your scope members and they will be directly updated to your d3 elements, in this case svg circles. In the angular controller (which receives the instance before the directive that draws the d3 objects).

  $scope.circles = []; for (var i = 0; i < 50; i++) { $scope.circles.push(new Circle()); } setInterval(function () { $scope.circles.forEach(function (d, i) { $scope.circles[i] = new Circle(); }); $scope.$digest(); }, 2000); 

Notice the call to $ digest, which tells angular to digest the changed area; this will change the values ​​for the SVG circle elements. For something like animation, etc. Now d3 is no longer responding, and you will need to manually or use a different template.

+3
May 30 '13 at 21:51
source share

You can also follow this / screencast guide to learn how to use D3 with angular. This is slightly different because it uses a wrapper library around d3 called rickshaw, which provides some graphic data, but the approach is exactly the same:

http://tagtree.tv/d3-with-rickshaw-and-angular

0
Jan 07 '14 at 14:41
source share

If we use d3 inside the directive to generate elements with other Angular directives (I think you will find this pretty general requirement), you can call $compile at the end of the UPDATE phase of the rendering process using the call() method. Like this (if we create a bunch of circles):

 mySvg.selectAll("circle") .data(scope.nodes) .enter() .append("circle") .attr("someDirective") .call(function(){ $compile(this[0].parentNode)(scope); }); 
0
Jul 16 '14 at 6:44
source share



All Articles