Sam Stites

Moving from Backbone to Angular Part I

11 June 2014 - Redwood City, CA

At bina, we have two products: bina portal and bina annotation platform. While the annotation platform has been written from the ground-up in angular, the bina portal was written in backbone. It’s also one of those applications which has grown into a monolithic zombie over the years. It’s got to go, but it can’t be canned. Taking on the codebase headfirst isn’t really an option for us as it means that we will have a brand-new product which won’t be user-tested. I’m sure many of you are looking at similar issues. The approach we’re taking at bina is to have angular and backbone coexist -backbone is a library, not a framework, afterall- and then slowly have angular take over. Let’s get started.

Coexisting with Require.js

I’m over require.js. It had it’s glory days, but it’s been on its way out since browserify, it makes for massive code, and is just an overall pain. I’m not saying switch to browserify (yet), but we have a ton of require.js in our code and we don’t really want it anymore. How to solve this problem: just put angular in with some good old-fashioned script tags in global scope and declare all of the script tags as you would with a normal application. After you have figured out how you want to structure your application (we’ve chosen google’s recommended file structure), add them into your project as desired - but before we add angular to our DOM elements, we need to take a closer look at bootstrap.

Rebuilding from the inside-out, feature-first

We’re building angular from the inside-out. Our first feature on the list is a pretty complex modal/lightbox which allows a user to navigate through a shared network file storage. First things first, get rid of all that Backbone code. Well, just enough so that it only serves up our partial HTML element. Here you should actually start building your feature only don’t declare any ng-app instead we’re going to bootstrap our application manually. Add in <script>angular.bootstrap(document, ['myApp']);</script> at the end of this partial and watch angular kick off as we want!

A closer look at angular.bootstrap

If you’re declaring an angular application the normal way, you probably have an ng-app somewhere at the top of the page. Well, when angular reads something like <html ng-app="myApp"> it will see that attribute and immediately start loading as soon as the DOMContentLoaded event fires (unless you’re working with legacy IE). We don’t want that though, so instead there are a few other ways we can kick off angular, manually. We can either invoke bootstrap by initiating the app on the document (as suggeted in the previous section) like so:

    angular.bootstrap(document, ['myApp']);

or invoke it on a more specific element using angular’s element selector:

    angular.bootstrap(angular.element('body')[0], ['myApp']);

Similarly, in the Angular documentation there is the following code example:

    angular.element(document).ready(function() {
        angular.bootstrap(document);
    });

This does something similar to a $(document).ready function in jquery, which is nothing new. The usage of bootstrap is misleading, however, since there is no app being invoked. This will only kickoff angular but not any angular modules/application you have declared. Be careful of this!

Bootstrapping twice and what’s coming up

It’s important to also note that if you declare both a <script>angular.bootstrap(document, ['myApp']);</script> as well as something similar to <html ng-app="myApp"> angular will error, claiming that myApp has already been bootstrapped. This is because, as mentioned, as soon as <html ng-app="myApp"> is read, angular will kick off. So there is no need to declare your application anywhere! Next up will be moving from modal to an actual page-view and setting up ui-router with lightboxes!