This is a good detailed guide but I think I'm missing something here. I can't quite formalize it but it has something to do with this:
> You may be wondering how we'll go about adding Axises to our graph, but here be dragons, so I'll leave that aside for the moment.
Uh, OK...having axes (and labels) is pretty integral to many charts and is pretty trivial in D3. If Angular is to replace much of the data-binding in D3, as the OP proposes, then I think there has to be less ad hoc hacking of Angular things to do what's relatively easy in D3. This reads more like a guide of how to get D3 (or rather, SVG charts) in a situation in which you cannot really use D3.
Think of d3 as a framework and a standard library. This post is about replacing the framework. However, d3 still has a load of ready made controls such as the axes. These don't exist for this new approach yet, at least not natively.
But I have released code (see the bottom of the post or just https://github.com/resin-io/triangular.js ) that allows Angular/SVG graphs to add axes. Just didn't want to go deeper into documenting that too as I've gone past 2000 words already.
Hopefully in the future this will be done in pure angular, as these directives use more or less the old approach of encapsulating d3 in a directive. But at least they are re-usable.
Why would you want to rewrite a stable, complete and extensive visualization framework within your MVC framework? d3 should sit at a lower level, the approach of containing the implementation to a directive looks much sounder.
i love angular but i dont really like the notion of having to reinvent the wheel with it.
I read about how one should ditch jquery plugins and rewrite them the "pure angular way" which makes sense for smaller stuff but there are so many very useful jquery plugins that have been around for years with alot of people working on them.
D3 is not a jquery plugin but why would i want to rewrite it for use in a specific framework ? When the next framework comes along that rewrite is more or less useless..If Angular is going to be the same standard as jQuery has become this is fine, but with current crop of competitors and the fast moving market i doubt it.
>I read about how one should ditch jquery plugins and rewrite them the "pure angular way" which makes sense for smaller stuff but there are so many very useful jquery plugins that have been around for years with alot of people working on them.
Actually it's supposed to make sense for the larger stuff -- Angular is not something to just replace a few small bindings in a your page while you do the rest of the stuff in 2005 way.
As for those "jQuery plugins that have been around for years" most of them are badly coded rubbish compared to what you're supposed to write in Angular style.
> Angular is not something to just replace a few small bindings in a your page while you do the rest of the stuff in 2005 way.
If we're talking about the jQuery way, let's at least say "2006", since that's when it was released, though it arguably didn't become "the" way for another few years afterwards. The big news in 2005/2006 was still Prototype.js.
> most of them are badly coded rubbish compared to what you're supposed to write in Angular style.
Or we don't have the benefit of 5 years of hindsight about what's problematic (or, "rubbish", if you will) when it comes to Angular style.
From my understanding other frameworks like Ember rely heavily on jQuery, unfortunately i havent really worked with them so i dont know what that means for plugins. We can not reuse angular directives in Ember/Backbone/Meteor so it doesnt make sense to spend the effort to reimplment bigger plugins/libraries imo.
It would actually be the other way round, you build your app in angular and for some specific view related code you use a proven and stable jQuery plugin, which imo still makes sense.
Furthermore you are being hyberbolic, jQ wasnt even released in 2005. In reality, when i have a client project with tight deadlines to finish and i need drag and drop functionality (as an example), i have little motivation to rewrite that just to avoid a jquery plugin that does the same thing and is much more mature.
A framework tries to take a platform and build another layer of abstraction on top of it. Ideally the developer should never have to cross that layer of abstraction except to learn more about it or to improve it.
A wrapper can keep the layer of abstraction intact for simple uses bit eventually the abstraction leaks, and demand for a replacement that's native to the framework is created.
This is interesting, but I'm not really sure what you get from it.
d3 and direct manipulation of SVGs are both so low level that make a decent looking chart requires a bit of boilerplate. That boilerplate should get wrapped inside of a directive and once you've done that, the specifics of how the directive is implemented don't matter too much.
It would be nice to use one language for data binding; I think angular would end up being a lot more verbose and prevent some of the nice things you can do with .call() and .transition() though. Additionally, I don't think 'creating a hole in the DOM' is necessary a bad thing. Sending graphs only the information that they need separates concerns nicely, resulting in more modular and maintainable code.
Even if it all gets buried under high-level visualisations, it's better to have fewer moving parts and a smaller cognitive model in case you do need to dive in. But the premise of d3 is that you tweak your visualisations. There are other libraries like raphael that are supposed to be higher level.
But there are many times you need to create something new. At least I've had to, maybe I'm atypical. And when that time comes, I prefer manipulating familiar HTML and AngularJS that I also already know, than needing to understand yet another toolkit's approach to bindings.
Awesome stuff. I’ve been going through JS libraries looking for better approaches to DOM manipulation. Previous examples of Angular with D3 were hard to use for my needs (though my lack of Angular as well as D3 skills didn’t help). I decided to implement Angular parts by myself (data binding, event bus), since the integration gave me headache with few returns.
I saw in twitter that you already got a ping from Rich Harris of Ractive fame. Hopefully you have time to blog about your experience on that front. I really liked working with Ractive, but couldn’t figure out how to combine D3’s functionality with it (like path and axis objects). Your post certainly gave me great pointers. Also, I did not manage to build complex tables with Mustache templates. On that front I hope React from Facebook is even better, but my testing is till ongoing.
I’d like to see a library on top of D3 that would use its extensive algorithms without the DOM manipulation. Your approach seems great for Angular use, where I probably shall return also. Still, with Ractive getting visualization going was really easy (not to mention fun) and React promises great performance in addition of strong component structure. D3 however has so much more for visualization at this point (geo module, scales to name a few).
Thanks for the kind words. Truth be told, I didn't expect this post to do this well, and also I am learning a lot from all the responses. Unfortunately I do run a startup, so I am not sure how much more time I have to put on this. Hopefully the ideas herein will ignite someone to actually get that proper d3/angular integration going. Fingers crossed.
I think you're missing a lot of the core concepts around visualisation. d3 aside (for now) you need to consider what visualisation is. Your focus is on charts alone will prevent this from getting any traction. d3 is a framework but it is also in a way, a visualisation kernel. This means that it gives the individual flexibility to create and design interactive information visualisations without being hindered by whatever is enforced by some charting library (only limited by the DOM or whatever scene graph it is working with).
d3 can also be viewed as an extension of the concept of 'grammar of graphics' (for a reference implementation of the grammar of graphics see vega (http://trifacta.github.io/vega) or ggplot2).
If you're plan around this is to build a system in which angular handles a lot of the data binding work, I would recommend re-implementing something like vega in angular. Because this would be more compelling than creating yet another charting library that is just built using some combination of d3's data manipulation and angular DOM style. nvd3.js, chart.js, yui-chart, etc. all run into this point where the libraries are simple tools for developers to use but do not have the extensibility of a framework like d3 that allows more freedom in the design.
Now lets say you create a competitor to vega, the key differentiator would be animation, assuming transitions are trivial as you've explained in this post, I have very minimal experience aside slides and videos in angular to comment. While vega will have: canvas scene graph support, potential to build on top of systems like WebGL, native iOS, or native Android. You will then be tasked to figure out the 'grammar of interactions' (https://github.com/trifacta/vega/issues/28) in order to allow attributes to differentiate yourself from vega which is going to be a very hard (but fun!) task.
Aside: d3's line function isn't refreshed as new data is inputed (meaning that you would either have to do this inside of some custom directive (towards the vega style implementation) or do some hack-ish 'tick' style system (the reason force directed is being updated is due to the fact that it has it's own very small physics model which you are leveraging on tick, (also 'ticks' do not harness angular's or d3's data binding concept well))).
I do think there is space for a true competitor to d3.js that takes a more OOP and stateful approach (what the root of your annoyance with d3 seems to be). While there may be room for this, I also feel (note emotion not backed with fact) like these concepts are also what will build too many limitations that will hinder the project itself. This competitor will likely live within the web components community once it's no longer dependent on angular.js, but will likely hit walls (just different walls than the ones you're currently frustrated with d3.js) that are going to be hard to get through.
I have thought about this stuff in the past (http://bl.ocks.org/milroc/5519819http://youtu.be/Hd2rye9a9kk) and recommended a wrapped directive approach for angular.js (and other MV*) but as I said above the next steps are going to be MUCH more difficult than we expect.
I have been reading Grammar of Graphics, but it’s a slow going. I don’t yet see where the connection is with D3 and the Grammar, though (probably since I lack knowledge of the Grammar and don’t yet grasp the whole of D3). D3 works best with SVG constructs, where elements and attributes are manipulated based on what functions return. These functions then react to data, but D3 doesn’t really know what is in the data. It merely binds it to element’s __data__ attribute implicitly so it can know what to change when node gets selected. It’s the developer’s job to choose the right elements and attributes where results should be placed. Resulting graphic is an SVG document, which can look as a cohesive graph if developer gets the parameters right. This structure is often hard coded into script and not done with specific grammar that could calculate the graphic parameters consistently and reliably. This might be since D3 is intentionally low-level, but then there are parts that try to do more abstract things (like axes, that generate SVG directly). I feel this contributes to the lack of reusability.
Popularity of frameworks like Angular and the recent appearance of Ractive and React, as well as Fastdom (not to mention ClojureScript) suggests to me, that easy, efficient and reusable DOM manipulation is a hard problem and there can be many solutions. Its because of this I’d like to keep using D3’s great functionality (for me the scales and geo module) without its use of selections and W3C DOM API. There are other ways to declare a graphic and bind it to data, but calculating points for lines should not be coupled to a particular style of DOM manipulation. I like D3 a lot for discrete visualizations, but creating many interdependent graphics (like map and bar chart from the same data with interactivity between them) is not as easy as with, say, Ractive.
What I understand of Vega is that it works as a kind of grammar for graphics, but one that completely encapsulates the DOM manipulation. This allows it to support other render target, like canvas. I feel that this is opposite of what Alexandros is suggesting, that is to use D3 where it is good, but not parts which clash with Angular’s view of the DOM. If Vega makes it easier to use its functionality without the renderer, that would be great, but I don’t know how well it supports D3’s great functionality. This is on my study list, though.
Really cool, I'm sure there are projects where this would be very helpful (although I don't see either of Angular or D3 replacing each other any time soon).
The ng-attr-x thing is a neat hack but it's a bit unwieldy. How about adding a d3-svg directive that turns itself into an svg element once Angular is done loading. You can hide it with CSS so it doesn't flash up random garbage on the screen and within it you can use regular SVG attributes.
I went along the path that using a directive to trigger D3 updates when $scope changes in AngularJS is a much better idea that throwing the baby out with the bathwater. D3 is incredibly powerful for visualisations, and it benefits greatly from simply tying it into the automatic $scope updates in AngularJS.
> You may be wondering how we'll go about adding Axises to our graph, but here be dragons, so I'll leave that aside for the moment.
Uh, OK...having axes (and labels) is pretty integral to many charts and is pretty trivial in D3. If Angular is to replace much of the data-binding in D3, as the OP proposes, then I think there has to be less ad hoc hacking of Angular things to do what's relatively easy in D3. This reads more like a guide of how to get D3 (or rather, SVG charts) in a situation in which you cannot really use D3.