

Replacing most of D3.js with pure SVG and AngularJS - alexandros
http://alexandros.resin.io/angular-d3-svg/

======
milroc
Alexandros,

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](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](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/5519819](http://bl.ocks.org/milroc/5519819)
[http://youtu.be/Hd2rye9a9kk](http://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.

Cheers,

Miles

@milr0c

~~~
jarpineh
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.

------
ricardobeat
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.

------
kayoone
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.

~~~
coldtea
> _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.

~~~
wwweston
> 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.

------
1wheel
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.

If you haven't read it, [http://bleedingedgepress.com/our-books/developing-
a-d3-js-ed...](http://bleedingedgepress.com/our-books/developing-a-d3-js-
edge/) is pretty good.

~~~
alexandros
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.

------
jarpineh
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).

~~~
alexandros
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.

------
tmcw
For the opposite: [http://macwright.org/2013/07/07/d3-for-
html.html](http://macwright.org/2013/07/07/d3-for-html.html)

------
coherentpony
I can't seem to play with any of the graphs interactively. Is that
intentional? Also, this site completely hi-jacks my 'Back' button.

~~~
alexandros
Apologies for the 'back' hijack. It could have something to do with the
plnkr.co embeds? Otherwise the page is pretty simple.

The graphs aren't interactive in their current state (but there's nothing
stopping them from being made interactive).

~~~
glutamate
See here for interactive plots with AngularJS+D3:
[https://bayeshive.com/blog/12/interactive-plots-with-the-
rad...](https://bayeshive.com/blog/12/interactive-plots-with-the-radian-ui)

------
almost
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.

------
beefsack
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.

[https://github.com/beefsack/angular-d3](https://github.com/beefsack/angular-d3)

------
danso
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.

~~~
alexandros
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](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.

