0

So I am building a table dynamically, roughtly like this

<tbody ng-repeat="d in data">
<td>{{d.name}}</td>
<td>{{d.dircleColor}}</td>   
<td id="a{{d.index}}>{{d.someOtherData}}</td>
...

"data" is an array, $scope.data in the Controller. Basic Angular, works very well.

Now, I also have to add a svg element (D3.js) into one of those dynamically generated <td></td>s

These have to correspond to the visualization that is also based on $scope.data, so that the red circle in the graph corresponds to the red circle in the table, and the user knows where to look for the information.

My biggest hope is a directive

.directive('dirCircle', function () {
   return function ($scope, elm, attrs) {                        
     var vis = d3.select(elm[0]).append("svg").attr("width", w).
        attr("height", h).attr("class", "circlesClass");
     node.append("svg:text")    [... more styling...]

This works, but at the moment I don't know how to tell the directive, which color my little svg-circle element should have. This information is in the $scope.data - array. But just accessing the $scope would not be enough. I need the information of the "current" element as it is drawn. Is that possible?


If this is not possible, here are some possible workarounds:

1) If the directive could become "self-aware" and look around the DOM in which it was put, that could help. Notice in my above code I have <td id="a{{d.index}}>...

The "a" is just there because ids start with a letter. d.index identifies the relevant data in my array, so if I can access $scope.data from my directive...?

2) generating D3 like you would normally, but putting it into the dynamically generated table cells like so:

for (var i = 0; i < _data.length; i++) {
var svgContainer = d3.select("#a" + _data[i].index).append("svg")  //circleData[0].ci
            .attr("width", 20)
            .attr("height", 20)
            .attr("class", "circlesOnTheRight");

works, however, the "compilation" from the "html-template" (the ng-repeat/{{...}} - stuff) always comes at the end. If new elements are added to the array, my function would always fire before angular creates the new table cells. When I tried it, even $scope.$on('includeContentLoaded', alert("...")); fires before angular is done.

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
graph
  • 367
  • 1
  • 6
  • 18

1 Answers1

1

I don't know how to tell the directive, which color my little svg-circle element should have. This information is in the $scope.data

Pass the color as an attribute on the same element where your directive will be used (wherever that is):

<some_element dir-circle the-color="d.color??"></some_element>

Then in your directive:

return function ($scope, elm, attrs) { 
   // $scope.$eval(attrs.theColor) contains your color
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • also include scope:{color:'@theColor'} in your code to inherit the scope from parent scope – Ajay Beniwal Feb 01 '13 at 06:41
  • thanks. I just used ($scope.$eval(attrs.theColor)); to get hold of the data. Still amazing that the "attr" actually refers to the "real" attributes in the DOM. And that you can make custom attributes in the first place. Magic! – graph Feb 01 '13 at 09:22
  • @Ajay beni: not 100% sure where your line would go in my code and how exactly it works. I just did ".directive('dirCircle', function () { return function ($scope, elm, attrs) { followed by the code that I already had. It's not the restrict-replace-scope-template-kind of directive. Sorry, I'm still trying to understand this better! – graph Feb 01 '13 at 09:29
  • @graph, I would recommend the following for learning more about scope inheritance and directive scopes: [What are the nuances of prototypal scope inheritance?](http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs) – Mark Rajcok Feb 01 '13 at 16:09
  • @Ajay, using `scope:{...}` creates a new isolate scope that does _not_ inherit from the parent scope. Also, with the @ syntax, attrs.$observe() would need to be used to get the value (asynchronously). – Mark Rajcok Feb 07 '13 at 21:03