Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 and two-way data binding

I am interested in the current best practices and solutions for using the data driven documents library with two-way AJAX data bindings. More specifically I am wondering how d3 should be best integrated with libs supporting two-way data bindings such as Angular or Knockout.

The obvious conflicts that arise stem from the fact that d3 and the AJAX libs are both inserting data to the DOM, which basically means that one has to wrap the other.

like image 859
B M Avatar asked Mar 11 '15 13:03

B M


People also ask

What D3 function do we use to perform the data binding?

D3 is data driven. The data() function is used to join the specified array of data to the selected DOM elements and return the updated selection.

What is data binding in D3?

D3 data selections. Data selections are the core of D3's data binding API. A data selection is created by diffing an array of data against a DOM selection. This example selects . app-user DOM elements and matches them to an array of user data.

What are two-way data binding?

In a two-way binding, the data flow is bi-directional. This means that the flow of code is from ts file to Html file as well as from Html file to ts file. In order to achieve a two-way binding, we will use ngModel or banana in a box syntax.

What is D3 function?

D3 allows you to bind arbitrary data to a Document Object Model (DOM), and then apply data-driven transformations to the document. For example, you can use D3 to generate an HTML table from an array of numbers. Or, use the same data to create an interactive SVG bar chart with smooth transitions and interaction.


1 Answers

About Data on DOM

You were worried about the data inserted to the DOM. This are some of the properties added:

  • D3js: __data__, __onmouseover.force, __onmouseout.force, __onmousedown.drag, __ontouchstart.drag, __onmousedown
  • AngularJS: value, type, version, align, ng339

So there's no colisions and no need to wrap one into another. You can test this using Object.keys(SOME_DOM_ELEMENT); and Object.keys(SOME_DOM_ELEMENT.__proto__);

About Implementation

Pure javascript

This is how you assign data to D3js:

d3selector.data( myNameSpace.myDataObject );

And this is my data binding approach using watch: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/watch

d3selector
myNameSpace.watch('myDataObject', function (id, oldval, newval) {
    d3selector.data( newval );
    return newval;
});

This way, everytime you change myNameSpace.myDataObject the data used by D3js will be updated too. But this will only work on Firefox.

AngularJS

There's an answer in this question Angular + d3.js: Data binding with SVG text attr? that explains how to do it using $watch.

Is similar to the Firefox watch:

directive('myDirective', function ( /* dependencies */ ) {

    // Imagine your $scope has myDataObject
    $scope.$watch('myDataObject', function (newVal, oldVal) {
        d3selector.data(newVal);
    });

}

Now everytime you change myDataObject in the $scope the data of D3js will be updated too.

More info

Here is an example of two way data binding using polymer: http://bl.ocks.org/psealock/a4f1e24535f0353d91ea you can test it here: http://bl.ocks.org/psealock/raw/a4f1e24535f0353d91ea/

As you can see in refreshChart the binding is not really being used. Instead, on the event triggered when the data changes, D3js loads the new data:

this.g.data(this.pie(this.data));

D3js is not prepared to listen for changes on the data, unless you use the data method. That's why the already rendered data will not change.

If in the future data bindings were implemented, I guess there will be a new method on selection:

selection.update - return placeholders for updated elements.

similar to the current enter and exit:

selection.enter - returns placeholders for missing elements.

selection.exit - returns elements that are no longer needed.

removing the need to create refresh functions.

like image 57
Gatsbimantico Avatar answered Oct 20 '22 01:10

Gatsbimantico