Angular + d3.js: data binding with SVG text?

I am working on a visualization that includes updating a text element that appears inside a circle. Sort of:

<g> <circle></circle> <text>My text that needs updating</text> </g> 

Along with this small visual is the d3 brush, used as a slider. In the / brushend brush, I need <text>Update the text here</text> based on data related to the time scale along the x axis of the slider.

I have two Angular directives. One that contains a circle, the other is a slider. In my slider directive, I call:

$rootScope.$emit('brushing'); and setting the rootScope variable according to my data, $rootScope.myNewValue = newValue; when the slip occurs

Then I listen to this in my other directive and update text.attr as rootScope var:

$rootScope.$on('brushing', function () { myText.text($rootScope.myNewValue); });

Where:

 var myText = svg.append('text') .text('I'm trying to update this text..'); 

... in the d3 part of the code

Performing such actions seems to work, but I'm wondering if there is a way to bind data directly when initializing myText:

 var myText = svg.append('text) .text($rootScope.myNewValue); 

Thus, the value is automatically updated without the need for generation and listening. I tried scope.$apply in the directive, but it seems to have no effect.

Has anyone come across a similar scenario when using d3 with Angular?

0
source share
1 answer

You can wrap the D3JS code in a directive, and then use the passed property and see if it is changed to update the D3JS code accordingly (keeping a link to svg text is still probably the best choice). For an example, see My directive below, where I use val to update the data used on the histogram display (note that I have not dealt with transitions yet, and the codes are a bit messy, but I hope you see a common point)

 directive('barChart', function ( /* dependencies */ ) { // define constants and helpers used for the directive var width = 600, height = 80; return { restrict: 'E', // the directive can be invoked only by using <bar-chart></bar-chart> tag in the template scope: { // attributes bound to the scope of the directive val: '=' }, link: function (scope, element, attrs) { // initialization, done once per my-directive tag in template. If my-directive is within an // ng-repeat-ed template then it will be called every time ngRepeat creates a new copy of the template. // set up initial svg object var vis = d3.select(element[0]) .append("svg") .attr("class", "chart") .attr("width", width) .attr("height", height); // whenever the bound 'exp' expression changes, execute this scope.$watch('val', function (newVal, oldVal) { // clear the elements inside of the directive vis.selectAll('*').remove(); vis.attr("height", newVal.length*22); // if 'val' is undefined, exit if (!newVal) { return; } var totalDataSetSize = 0; for (var i = 0; i < newVal.length; i++) { totalDataSetSize += newVal[i].data.length }; function calcBarWidth(d) { return (totalDataSetSize==0)?0:d.data.length/totalDataSetSize*420; } vis.selectAll("rect") .data(newVal) .enter().append("rect") .attr("y", function(d, i) { return i*20; }) .attr("width", calcBarWidth) .attr("height", function(d) {return 20}); vis.selectAll("text") .data(newVal) .enter().append("text") .attr("x", function(d) { return calcBarWidth(d)+10}) .attr("y", function(d, i) { return (i+1)*20; }) .attr("dy", "-.3em") // vertical-align: middle .style("font-size", ".7em") .attr("fill", "black") .attr("text-anchor", "beginning") // text-align: right .text(function(d,i){ return d.data.length.toString() + " " + d.label}) },true); } }; }) 
+1
source

Source: https://habr.com/ru/post/983649/


All Articles