D3-driven directive transition doesn't work inside ng-repeat

I am trying to include d3 code inside a directive.

However, when my directive is inside ng-repeat no transitions will be executed.

Here's the JSFiddle of the problem: http://jsfiddle.net/hLtweg8L/1/ : you can see that when you click on the button, the position of the rectangles does not change smoothly and 'append'

is logged to the console again.

My directive is this:

myMod.directive('chart',function(){
  return {
    restrict:'A',
    scope:{
      data:'=',
    },
      link:function(scope,elem,attrs){
          a=d3.select(elem[0]);
          rects=a.selectAll("rect").data(scope.data,function(d));

          rects.enter().append("rect")
             .attr("x",function(d,i){console.log('append');return i*50+"px"})
             .attr("y",100)
             .attr("width",35)
             .attr("height",function(d){return d.age*10+"px"})
             .attr("fill","blue")

          rects.transition().duration(200)
             .attr("x",function(d,i){console.log('append');return i*50+"px"})
             .attr("y",100)
             .attr("width",35)
             .attr("height",function(d){return d.age*10+"px"})
             .attr("fill","blue")
    }
  }
})

      

As far as I understand, the problem is that the elem

link passed inside the function does not match the ng-repeat update, so the append application calls more than once for the same data.

My question is, how can I use d3 transitions inside ng-repeat? (The corrected Jsfiddle helped a lot). Or why is elem not the same between different calls? Can I tell angular that the dom should not be removed and added again?

+3


source to share


1 answer


A couple of things are required:

  • If you don't want ng-repeat to create a new element, you need to use a parameter track by

    so it knows how to identify new or changed elements:

    <div ng-repeat="set in sets track by set.group">

  • D3 will not automatically see that the data has changed if your directive is not tracking changes.

      a=d3.select(elem[0]);
      scope.$watch('data', function() {
          updateGraph();
      });
    
          



Here is an alternative fiddle: http://jsfiddle.net/63tze4Lv/1/

+2


source







All Articles