ngUrlBind: Easily bind Angular scope properties to the URL hash.

Ever wished you didn't have to retrace your steps every time you refreshed your AngularJS project in development? Perhaps you wanted your users to be able to send you URLs that contain the relevant parts of the application's state for debugging purposes? Or that they simply could exchange their creations via URLs over IM and email?

ngUrlBind allows you to easily bind AngularJS scope properties to your URL hash.

See a simple example or an advanced example.

AngularJS's two-way binding allows you to bind data from a model to the DOM and back. ngUrlBind allows you to additionally bind data from an AngularJS model to the URL hash and back. Does that make it four-way binding?

While the whole Single-Page App thing is new and trendy, ngUrlBind is inspired by the "Hypermedia as the Engine of Application State" principle, one of the core components of REST's Uniform Interface constraint.

Why?

ngUrlBind is useful during development where you want to be able to hit refresh on your browser (or use livereload) without having AngularJS lose its scope state, or at least certain parts of it.

Subject to the limitations noted below, it is also useful in production, if you want your users to persist and exchange certain aspects of Angular's state. For instance think about exchange of URLs over email of IM, or just simple bookmarking.

We have made this as it's useful to us in both of these cases and are making it available to anyone else who may want to use it, improve it, or simply learn from the concept.

How does it work?

ngUrlBind's principle of operation is simple. Selected model properties are reflected to the URL hash as the AngularJS application is being used. They are then seeded back to the model when the page is loaded with the appropriate hash. We use the very elegant jsurl to serialise JSON data to the URL as it becomes both more readable and shorter than using Base64.

Binding a property

All you need is to inject the ngUrlBind service into your controller and call

ngUrlBind($scope, 'propertyName')

That's it. This will bind the user property of your current controller's scope to the URL hash.

Important: For the moment, only first-level properties are supported. So no dots in the 'propertyName' argument. Feel free to investigate and remove this limitation, pull requestes welcome.

Here's a more complete example:

angular.module('ngUrlBindExample', ['ngUrlBind'])  
    .controller('mainCtrl', function($scope, ngUrlBind){
        $scope.user = {}
        ngUrlBind($scope, 'user')
    })

This will bind the state of the user property to the URL hash. Refreshing the page will restore the state of the user object through the URL hash.

Known Limitations

A major limitation is that ngUrlBind doesn't play well with AngularJS routing. We're fairly confident this can be remedied, but haven't had the need for now.

Another limitation is that the each user action creates a new hash, which adds a step to the user's history. By strict HATEOAS this is correct, but this should probably be improved for the sake of UX and practicality.

I haven't done any performance testing, but I wouldn't be surprised if it wasn't fantastic at this point. In object.Observe() we trust.

ngUrlBind is not for everything, and it's not for everywhere. But it's got its uses.

Installation

ngUrlBind is available via Bower with a simple bower install ngUrlBind.

make sure ngUrlBind/dist/ngUrlBind.js is loaded before your angular module. ngUrlBind is wrapped in the Universal Module Definition so it supports AMD, CommonJS, and plain ol' global declaration via script tag.

Make your angular module require the 'urlScope' module and inject the ngUrlBind service into your controller. You're ready to go.

Development

The code is up on github. Fork it, star it, issue your issues, or push your pull requests.

To hack on it, you'll need to clone the repository, have gulp installed globally (via npm install -g gulp) and then run npm install.

Once you're set up run gulp build to convert the source to a js file in /dist or simply run gulp to build continuously with a watcher. The code in /example points to the version in /dist as a dead-simple way of testing.

Future

At the end of the day this is a simple little module that's been used non-trivially in only one project. There's undoubtedly lots to fix, for which we welcome your pull requests and issues.

Regardless of the module itself and its limitations, I find the concept for which this is a proof particularly interesting, especially combined with the ease of integrating it into an existing AngularJS project.

Bitcoin: A New Kind of Startup?

Ever heard of an idea whose time has come? A few minutes ago I read this comment by Paul Buchheit on Hacker News:

Here's another interesting (though imperfect) way of thinking about bitcoin: it's a decentralized corporation, where bitcoins are ownership shares and the business is money transfer, like a decentralized Western Union.

I have had this article in my drafts folder for a while, I reckon if I don't publish it now, I never will. So here it is.

Bitcoin seems to be exploding, with a huge ecosystem and passionate defenders popping up everywhere. Love it or hate it, and people do both with the heat of a thousand suns, it's gone much further than most thought it would when it got started. How can an un-owned good behave so intelligently, navigating legal, social, and physical constraints with gusto?

User netcan on HN hit the nail on the head:

Early adopters become like investors. There never was an explicit quid quo pro, but overall people involved early in bitcoin ended up owning a bunch of bitcoin.

The answer is that it's not really un-owned. Early adopters own large amounts of Bitcoin, and are therefore incentivised to advertise it, steer it to safety, and offer services that increase adoption. What's more, someone who creates a successful Bitcoin service, gathers more Bitcoin, becoming more and more invested in it by that fact.

If this were a startup, we might be seeing a generally similar pattern: Early investors and founders having a large share, new hires getting increasingly smaller shares but at increasing valuations, and star performers getting rewarded with equity. And this pattern results in a very well balanced incentive structure that has served many a startup well. Bitcoin takes this further with mining: Early adopters can earn a share in the startup, therefore becoming invested in its success. Another interesting point is that this 'startup' was being floated on the 'public market' since day one. Only, it's not a company, and it's unclear if anyone controls it at all. But you've never needed accreditation to buy a piece of it.

This post however is not about Bitcoin as such, but rather about the class of things that are like Bitcoin. Passions run wild on both sides of that debate, and I consider myself as an observer, along with the masses, waiting to see which way this will go. But interesting it definitely is, and what I am interested in is whether the BitCoin pattern could be adapted to a more traditional startup.

The nature of the Firm

Ronald Coase, was an economics professor who became famous for his 1937 work "The Nature of the Firm". In it, he posed a simple question: If markets are so great a coordination mechanism, why do we even have firms at all? Wouldn't the logical conclusion be that everyone would be a freelancer, arbitrarily configuring themselves into whatever shape the market commanded today? Surely large firms with the large coordination overheads they impose are a waste that should have been eliminated a long time ago. The fact that this has not come to pass was the question Coase grappled with and his answer was this: transaction costs. Yes, it would be great to have all that flexibility, but creating and destroying connections ad-hoc imposs a transaction cost. And that is where the reason for the existence of the corporation stems from. Corporations get economies of scale in the use of the pre-existing connections which they are composed of. And the harder connections are to create, the larger a corporation can become before its own diseconomies of scale catch up to it.

Here's where it becomes interesting. The Internet cuts down transaction costs, almost by definition. Want to meet people to work with? Google for them. Or join Meetup.com. Need infrastructure? Amazon. Accounting? Xero. One by one all the generic functions of a company have been getting factored out. But the structure of the corporation remains intact, as if from a different era. Shares, investors, founders, employment contracts, limited liability corporations, etc.

Bitcoin may be the first financial organisation of a new kind altogether. Transaction costs themselves have been wiped out. About as structured as Anonymous, but with everyone incentivised and motivated to help it grow. A thousand flowers blooming, with the internal BitCoin economy rewarding the winners. Even agility poster children, startups, can't match this level of incentive alignment and dynamicity.

Can this pattern be used in other startups, or is Bitcoin one-of-a-kind? While I can't immediately see how to connect the dots, something tells me the future looks more like this and less like your typical Big Corporation. Whichever way this goes, it's looking more and more exciting.

Using pure AngularJS + SVG to create the Resin.io logo

Our graphics designer is hard at work making the Resin.io logo and we've converged on a cube-in-cube logo that looks like a hexagon. But I wanted an easy way of playing with the ratios and colours, and photoshop was just too complex for this sort of thing. So I thought I could replicate the logo in SVG and use Angular to parameterise it, using the technique I discussed in my previous post It actually worked out even better than I expected:

You can see the code by clicking the coresponding button at the top right. A lot of the code is about having the interactive JSON object at the bottom which I found useful so team members could 'store' and exchange their favourite logo configurations, and also quite a bit of the code is going towards the colourpicker which I'm not terribly happy with.

That said, it's all 150 lines and was done over a couple of hours.

If anyone wants to recreate this in D3.js, I would really love to see that code. I am not implying that it will be bad code, I just can't even begin to think how to do something like that. And to a large extent, that's the benefit of the Angular+SVG technique: It's building blocks are much more intuitive, at the very least to me.

Replacing (most of) d3.js with pure SVG + AngularJS

Over the last few months, I've been feeling increasingly unsatisfied with the options we have for integration between d3.js and AngularJS. In my earlier projects, I used Brian Ford's approach of creating a directive for the visualisation I need, and adding the d3 code in the link function of the directive. This is simple and works, but it feels like a very superficial integration. Effectively the Angular directive creates a hole in the DOM processing cycle within which d3 can work.

The good guys at BayesHive came out with an alternative approach called Radian, that felt closer to what I wanted. They rely heavily on small, pre-existing Angular directives to declaratively create d3 visualisations. This means that a lot of the information about how to configure the graph lives in the HTML, as it should.

Thinking about it further though, what Radian is doing is using directives (masterfully) to trigger d3, to create SVG tags, so that the browser can finally render a visualisation. But if the browser already contains a declarative language that allows specifying visualisations in SVG, why do we have to jump through so many hoops?

Dividing responsibilities

Perhaps in order to understand the note of discord that's been bothering me, it may be best to take a step back and play a game. Out of D3 and Angular, try to guess which of the two has the following quote on its homepage:

"[ProjectX] allows you to bind arbitrary data to a Document Object Model (DOM), and then apply data-driven transformations to the document."

And which one has this:

"For example, you can use [ProjectX] to generate an HTML table from an array of numbers."

Or this:

"Create an interactive SVG bar chart with smooth transitions and interaction."

Educated guesses in hand, let's look at the answers.

The third one is easy. It's from D3's homepage. Angular can't create SVG charts. (or can it?) What's surprising is that the other two quotes are also from the D3 homepage.

It seems d3 sees itself as kind of a data binding library, that happens to be good at visualisations. This usually confuses newbies to no end, but makes sense once you get the hang of d3. But bindings are also a core pillar of Angular's way of working. So using both leads us to having two duelling libraries, both trying to control the DOM. In order to get what we want, we need to understand both and use both. This doesn't feel right. So before figuring out how to do the integration, it may be best to first decide who will do what.

Let's start without D3 for a moment

Perhaps the best way to continue this investigation is to try and instrument an SVG visualisation purely with AngularJS, and see what we could be missing. Afterall, SVG is markup that works in HTML5, and Angular is good at manipulating HTML5. Once this way of looking at visualisations sinks in, you might even wonder if we will need D3 at all.

Let's start by adding some data to our controller:

$scope.graph = {'width': 265, 'height': 134}

Then, we'll need an SVG element in our template. An Angular coder would probably write something like this:

<svg height="{graph.height}" width="{graph.width}"></svg>  

Simple, yes? Not so fast! This is the first pitfall you'd find if you go this route. Apparently SVG elements are more sensitive than other HTML5 elements, and don't accept invalid attribute values. This means that the SVG parser will throw errors before Angular has time to come in and replace the interpolated values. For this reason, AngularJS 1.1.4 added an excellent feature, ng-attr. If our template looks like this instead, it will work fine:

<svg ng-attr-height="{{graph.height}}" ng-attr-width="{{graph.width}}"></svg>  

That's because ng-attr-height does not trip up the SVG parser, not being a proper SVG attribute to begin with, and when Angular parses it it will convert it to the height attribute set to the correct value. As such, the SVG parser is never presented with an attribute that has an unparseable value, and never throws an error.

Let's now add some visual to our -isation. Perhaps something basic such as circles?

<svg ng-attr-height="{{graph.height}}" ng-attr-width="{{graph.width}}">  
    <circle ng-repeat="circle in circles" 
        ng-attr-cx="{{circle.x}}" 
        ng-attr-cy="{{circle.y}}" 
        ng-attr-r= "{{circle.r}}">
    </circle>
</svg>  

In our controller, we'll need to add the circles property. Let's seed it with some source data:

$scope.circles = [
    {'x': 15, 'y': 20, 'r':30},
    {'x': 35, 'y': 60, 'r':20},
    {'x': 55, 'y': 10, 'r':40},
]

This is what the end result looks like. Click on the "Code" button to review the full source of the running example below.

* Update: I have now made a much more substantial example of using plain AngularJS and SVG which you can see here*

Allright, this is starting to look like something. An SVG visualisation that can be generated (and updated!) directly from a JSON object. The code is quite terse and fully declarative. The bindings also work just fine using angular's fine ng-repeat machinery, so you can do fancy work just by modifying the $scope.circles object at runtime with regular JavaScript, as long as you work with Angular's digest cycle. To my eye, the HTML also looks much more approachable and modifiable than the equivalent D3 incantations.

In fact, if you want to add animation to your visualisation, AngularJS has a homegrown ngAnimate library, obviating the D3 .enter() and .exit() song-and-dance. Though one could make an argument that the enter/exit metaphor is still there in the CSS. If you want to know more about how to add animations to an AngularJS visualisation, you can do worse than this excellent tutorial by yearOfMoo, the primary coder behind ngAnimate. Adding animation to the above example is left as an exercise to the interested reader.

Or maybe we need D3 afterall?

So far so good, Angular can cope. But when trying to do the most famous of visualisations, the line graph, our approach hits a wall. Line graphs use svg paths, specified in a peculiar mini-language, which I presume hails from the depths of SVG's ancestry, possibly PostScript. It looks something like this:

<path d="M150 0 L75 200 L225 200 Z" />

This is where Angular falls down. What we need is the ability to convert a sequence of points to this path string, but Angular has no built-in machinery for this. We could perhaps implement a function to convert a series of points to an SVG path, but that would be a lot of code and thankfully there's no reason for that anyway. D3 has d3.svg.line() that generates just the right kind of string. It can even do some pretty sophisticated interpolations. What's more, due to d3's excellent modular design, we don't have to use the rest of d3 if we don't want to.

Say we have a series of points we want to convert into a line:

$scope.points = [
    {'x': 3,  'y': 7 },
    {'x': 5,  'y': 15},
    {'x': 7,  'y': 8 },
    {'x': 11, 'y': 17},
    {'x': 13, 'y': 13},
    {'x': 17, 'y': 23}
];

We could do that using d3's functions as follows:

x = d3.time.scale().range([0, $scope.graph.width]);  
y = d3.scale.linear().range([$scope.graph.height, 0]);

x.domain(d3.extent($scope.points, function(d) {return d.x}));  
y.domain(d3.extent($scope.points, function(d) {return d.y}));

$scope.line = d3.svg.line()
  .x(function(d) {return x(d.x);})
  .y(function(d) {return y(d.y);});

And this is what that looks like:

Here we've used d3's functions to generate the path for the line, but d3 itself never touches the DOM. That is left to Angular, keeping a clean division of responsibilities: Angular for binding, and d3 for visualisation domain magic.

You may be wondering how we'll go about adding Axes to our graph, but here be dragons, so I'll leave that aside for the moment.

And now for something a bit more complex

But what about all those beautiful diagrams d3 is known for? Like the force-directed graph for instance. How would we recreate that in Angular/SVG? It turns out that the force layout is heavily dependent on the d3.layout.force() engine. Thankfully this engine is more-or-less decoupled from the DOM so we can pair it with Angular quite nicely:

In the embedded window above, pressing 'Code', selecting a file, and then pressing 'Preview' again will show you the animation from the start.

The original D3 example this was based on can be found here for comparison. Dragging nodes doesn't work, but can be added by tacking on a 'draggable' directive, similar to this to the graph's nodes. Also, depending on your system, you may notice that the Angular version is a little slower than the pure-d3 version. This is an artefact of how d3's engines expect to be used. This will not be solved until either the force layout is re-implemented to respect Angular's digest cycle, or Angular implements object.observe(), (which Team Angular are working on), making the digest cycle a transparent internal detail.

Early days for an integrated approach

Overall, it seems that AngularJS implements the declarative, data-driven documents vision Mike Bostock had for d3. It's just that d3.js isn't a big part of the final picture when it comes to data binding. Angular, in the process of completing a disruption of the jQuery paradigm, has implemented many of d3's best ideas. d3.js was a pragmatic way of bringing these ideas to the fore by working in the visualisation space without upsetting the status quo of managing the DOM, but the ideas are so much more powerful when used everywhere, uniformly.

My own experience in doing visualisations using Angular/SVG first and judiciously adding d3 helper functions (or the occasional directive) when needed, is that I finally 'get' SVG a lot better, and feel much more empowered to do what I want, than when trying to manipulate D3's abstraction over SVG. But this only applies for the kinds of visualisations that can currently be done with the Angular/SVG combo. On the other hand, D3's nicely modular computation functions are an excellent API that mostly needs no change.

As of right now, anyone wanting to do Angular/SVG visualisations has no helpers or examples at their disposal, and will have to reinvent a few wheels. We're in early proof-of-concept days, with an architectural insight as the only guide. I wouldn't advise taking this anywhere near production, unless you know exactly what you're getting into, but if you would like to experiment with an avant-garde approach to visualisation, this is for you.

As people experiment more, I expect this state of affairs will change. Many of d3's functions can be used as-is. Others mix DOM updates with computation, so that pattern clashes with Angular.

D3 took us way forward in web visualisation. With AngularJS rapidly maturing, there's (theoretically) no longer a reason to use two separate ways of doing the same thing. Same as Bootstrap got integrated into Angular first with wrapper directives and then by a native re-implementation, I expect d3 to be first wrapped and then reimplemented in an Angular-compatible way.

Enter Triangular.js

I've already done some work in that direction with a library I call triangular.js (get it?). I've made what I have available on GitHub to use as you please. It is more of a code example than an actual codebase at the moment, mostly consisting of the pieces necessary to make a linechart that animates as the source data changes (another exercise for the abnormally interested reader!). For those of you brave enough, please do give it a look and send pull requests so we can build it into something more useful. As I said we're in the early days, so most of the philosophy around the library is open to rough consensus and running code. It's initial approach is to try and wrap the necessary parts of D3 into Angular directives, but inevitably, if this project is to be completed appropriately, it will need to replace parts of D3 with code that respects Angular's digest cycle.

The future is not actually about Angular

I may have tricked you into thinking that this post was about Angular with my writing so far. I did actually write it in the title, so you're not to blame. In fact, I doubt any non-Angular users have read this far. And that's too bad because this post isn't really about Angular, all things considered. In fact, Angular may just be a temporary step in having this sort of functionality built into every browser out there.

With Web Components and Template Binding coming down the standards pipeline, that day may not even be very far. We as web developers will have to learn to code in this style, and D3 will have to evolve for a world where browsers can deal with data-binding natively. If it continues to live as a framework in a world where its ideas about binding have dominated, it will have to focus on providing the additional computational functionality needed for beautiful visualisations. Same as AngularJS, d3's ultimate success may be to be no longer needed, when the Web can natively do what each library's authors thought the web should do.

Update: Check out Chris Garvis' adaptation of a bar chart if you're looking for some more sample code in the same style.

Update: @Rich_Harris pointed me towards RactiveJS which has bindings and strong SVG support. And it looks very pretty. Hopefully we'll get AngularJS to be that smooth too, soon enough.

I look forward to your comments, here or on Twitter.

The upside of being on the cutting edge

If you've ever gone near an enterprise IT setup, you've heard all the reasons why you should stick with tried-and-tested technology. The arguments are obvious:

  1. Mature technology will have had more time to get the bugs worked out of it.
  2. The ecosystem and toolingwill be more mature and better integrated.
  3. You can hire developers off the market easier.
  4. You can find people to sell you support contracts in case something does go wrong.

The opposing side is less easy to argue. It's like arguing for relaxing security at airports. You can have compelling arguments arguments, and still be defeated by fearmongering of the "but what if it fails" type. Afterall, nobody ever got fired for buying IBM.

If you're a startup founder (or looking to be), thankfully you're not at risk of being fired. You're at risk of your company failing to succeed before your limited resources run out.

But what can weigh the argument on the "bleeding edge" side?

The first and simple reason is that undeniably, new technology is more fun to work with. The 'fun' factor can be broken down to two different dimensions:

  1. New tech (hopefully) addresses issues with old technology, making it easier to work with. I.e. while the old school works with CVS/SVN, the new school can work with Git.

  2. The energy in a new community is hard to match. Forks, pull requests, exciting new directions. What's not to love?

But there are less obvious reasons to prefer the cutting edge. The first was captured by Paul Graham, and has to do with hiring:

But when you choose a language, you're also choosing a community. The programmers you'll be able to hire to work on a Java project won't be as smart as the ones you could get to work on a project written in Python. And the quality of your hackers probably matters more than the language you choose.

Of course this point is related to the fact that good hackers expect to have fun at work, and have the chops to work around rough edges.

Also let's not forget that new technology tends to get built on new technology. And some of that new technology may be that crucial feature that will give you a leg up on the competition.

Another reason, less obvious and discussed, is that on the cutting edge, you can identify opportunity.

Since most startups don't end up pursuing the business model they start with, it's a serendipity-enhancing idea to work on soil rich with opportunity. And you never know when you'll need some serendipity. When dotCloud started working on Docker as an internal project, they didn't anticipate that they'd be renaming their company to Docker Inc. in less than a year. But working with LXC at scale meant they were uniquely placed to see the opportunity and eventually make that leap.

In the case of resin.io, we were given a digital signage project to work on. That the industry term for screens that display information. Instead of using the 'traditional' approach of Flash and proprietary solutions, we decided to approach it as if it was a web development project. That put us on the cutting edge of some really interesting questions around HTML5/JavaScript and code deployment in distributed systems, as it turned out. We worked on it for 2 years and realised that a lot of the problems we were solving would actually be of use to other developers. Afterall we were only forced into solving them because someone else hadn't.

So overall, there is a lot to recommend sticking with the tried and tested. If you're sending rockets to Mars, by all means, use the most hardened technology you can get your hands on. The extra development time will pay for itself, and engineers will work with any technology they have to if their code runs on a computer that is scheduled to depart from the earth's gravitational pull. But if you're doing a startup, a web project, or anything where you have to balance newness and maturity of your technology stack, do consider the arguments for taking a chance on newer technologies. Afterall, what you start with is what will become your legacy technology tomorrow. Other things equal, it's best that your codebase is built on as fresh a foundation as possible.