I\'m working on a medium sized application that is going to include a lot of D3 charts / interactions in it. I\'m wondering if anyone has tried to use Backbone, Angular, or
I recently gave a talk on this very topic, here are some links: Video · Code · Slides
I've done some smaller projects using similar methods to meetamit, but have recently started exploring Ember + D3. I haven't done much yet, but I think Ember has a lot to offer that could simplify building these types of app. Some things that come to mind:
Computed properties: you'll often be displaying aggregates, so slicing your data using computed properties means you just have to call your chart's update function whenever the data changes, and you're good to go. No more worrying about sending off an event to every view that will change when one specific part of your data changes. Plus, these will probably be properties on your controllers, instead of being calculated within a specific chart or view, which will make reuse much easier.
Storing state: I had a tough time figuring out the best way to store state in Backbone. I started out trying to coordinate everything via events, but in the end landed on having a separate State model which acted as the brains of the whole system.
I didn't get around to using Backbone's router much, but Ember's router + focus on state has made this design challenge easier for me so far. If you build within the system, you can click around your filters and controls, and everything just works. It may be possible to do exactly the same thing in Backbone, but there's something to be said for seriously reducing your cognitive load. You can also explicitly use a StateManager object - there may be some really interesting solutions here, though I haven't explored them yet.
Again, my experience with this combo is shallow, but if my instinct is right there are going to be many gains from building visualizations within Ember's conventions.
If you haven't already come across this, Square put up an article briefly covering their experience building an interactive dashboard with Ember + D3.
Keep us up to date on your progress + any insights you come across, and good luck!
I have worked with Backbone+d3 and with Angular+d3 a little bit.
Backbone suffer with memory leaks problem and if you use backbone you should be accurate with garbage collection. However as mentioned before marionet or chaplin can easily solve this problem. If you want to have light and fast application I recommend you to use react engine for views and backbone models for other needs.
As to Angular it has more strict structure. However, I believe that it will be almost the same logic as Backbone. Angular takes care about architecture and everything what is needed just write code by refs and it will be maintable. Unlike backbone, where structure is your option.
I recommend you to compare routing, bindings, models to select right framework, but not views.
I always choose backbone + smths, often React. Because it is flexible and easy to manage application views. F.e. when we found react we moved from backbone to react to fix our mremory leak problems. However applicarion had about 50 views with different data visualisation tools with many controls. And we moved views step by step in two month. It is difficult to do same thing with same efforts in angular.
We used d3 with Backbone pretty extensively on a project that consisted of multiple "scenes". Each scene contained a set of different charts, and a user has the ability navigate from one scene to another. These scenes and their content all needed to be highly configurable (e.g. label colors and formatting, or indicating which data params should be plotted on a given axis).
D3 (rightfully) doesn't provide a view management system, which is where Backbone took over. Backbone Views served as wrappers for d3 charts. Predictably, Backbone Models served as the carriers of the d3-plotted data. But more interestingly, we also found that they served well as a means of controlling the appearance and behavior of the d3 code contained within the Backbone Views; essentially they served as view models. Since d3 promotes passing functions as arguments into other functions, these Backbone Models-as-view-models ended up holding many functions in them.
The following is a simplistic example, but picture doing this with dozens of properties. Using coffeescript here, because it's shorter (and better).
First, there's the model, which we instantiate inside (for example) a router's event handler. We populate this model with functions that will be applied to d3 selectors.
barChartModel = new Backbone.Model
barColor: (d, i) -> if d.profits < 0 then "red" else "green"
barLengthVal: (d, i) -> return bar.profits #// profits will be the prop we graph
onClick: (d, i) ->
console.log "We are", if d.profits <= 0 then "losing" else "making", "money"
data: someJsonWeLoaded
We pass this model into a new view:
barChartView = new BarChartView
el: "#the_bar_chart"
model: barChartModel
A view might be implemented like this:
class BarChartView extends Backbone.View
render: ->
bars = d3.select(@el)
.selectAll('.bar')
.data(@model.get 'data') # <---- THIS
bars.enter()
.attr('class', 'bar')
.attr('fill', @model.get 'barColor') # <---- THIS
.attr('height', (d, i) ->
@barLengthScale @model.get('barLengthVal')(d, i) # <---- AND THIS
)
.on('click', @model.get 'onClick') # <---- INTERACTIVITY TOO
initialize: ->
@barLengthScale = d3.scale.linear()
.domain([-100, 100]) # <---- THIS COULD ALSO COME FROM MODEL
.range([0, @$el.height()])
@render()
I think these types of questions don't really have a right answer IMO, it's like asking someone whether they should choose a Subaru or a Toyota, when all they need to do is get from a to b :) Anyway, using AngularJS and D3 at the moment, so far so good :) There is a nice AngularJS directive for D3 and NVD3, if you do choose to go with AngularJS.
Also, check out this excellent post on combining D3 with AngularJS.
Happy exploring!
I use D3 on Angular since one year and I love the combination of both. Angular uses directives to create new and reusable HTML elements. When you have this knowlegde, you can encapsule a D3 visualization in an Angular directive without having D3 in your controllers or somewhere else. After that you can reuse the directive everywhere in your application to visualize your data. When working in a team of multiple Angular developers, the rest of your team doesn't need to know anything about D3, because your D3 code exists only in the directive.
Directives in Angular give you a flexible way of dealing with data. You can choose whether your data persists in your directive (then you will have a static reusable visualizaiton) or you make a data binding to a controller in your Angular application (then you will have a dynamic reusable visualization). The latter can be achieved by setting a scope in your directive
scope: { data: '=' /* bi-directional binding */ }
,
setting the data in your controller
$scope.data = [23,44,22];
and join both in your HTML element instance
<div your-new-d3-element data="data"></div>
.
Thats it!
Furthermore you can use watcher in your directive to watch changing data in your controller. A nice example of reusable d3 directives in Angular gives this example: http://bl.ocks.org/biovisualize/5372077
Moreover you can find an easy D3 on Angular setup in this article: http://goo.gl/hNS8k1 On this site you find further introductions how to use d3-plugins like the fisheye plugin in your Angular application or how to implement more complex d3 visualizations in Angular.
My group has used both angular and backbone with d3, and we like both for different reasons.
Backbone is a bit less opinionated about the way you construct your application, which is nice if you need to customize the way data is getting handled for performance. You generally integrate d3 with a backbone view.
One challenge of working with Backbone is memory management for complex views, but using marionette helps with that. Also Marionette's event aggregator (and specifically using request-response) is a good fit for centralized data sources for coordinated views if you want to use something like crossfilter or lunr.
Angular is more structured, and it is allows you to build up cool features very quickly. It has a steep learning curve, but I've found now that I'm understanding angular (having using it to develop an application for the past ~4 weeks), I've found that I can accomplish many of the same things I can in backbone without resorting to anything too hackish.
Like the request-response object in backbone marionette, using angular services allows you to build up complex views quickly. You'll need to avoid using angular's dirty checking on $scope data for complex data visualizations to keep your application from bogging down, so the code you write for working with your data in angular is going to end up looking a lot like the code you would write in backbone.
I had resisted angular's "magic" for a while, but I'm starting to get won over by the speed of development you can achieve because of all the built in directives, scope checking, and other goodies. Angular still allows you to poke around in its internals to speed up your code when that's required. This "digging" may take more time than in backbone (because the code base is more complex), but I've found that time lost in this phase is usually recouped by time saved avoiding common bugs like memory leaks in view code and writing boilerplate code like view rendering and data binding.