Writing Apps Part II: Angular.js and WinJS
April 18, 2014
Fat Guy in a Little Coat
This is the second in a series of articles about the experience of writing an app for the Windows 8 App Store. In the first I talked a bit about some of the good and bad of developing with WinJS, and hopefully showed some pointers if you want to go down that route. In this article I’m going to cover Angular.js, and how to successfully manage its relationship with WinJS.
MVC (model-view-Controller) frameworks seem to be hot stuff these days, with heavy-hitters like Knockout.js (sorry for the pun), Knockback, backbone, Spine,
For the uninitiated, the Model-View-Controller pattern separates different kinds of programming code into different locations. For instance, the code that tells the computer how things will look (often called “markup” or the “view”) will be in one place, the code that calls the shots, reacts to user clicks, etc will be somewhere else. It’s called the controller for obvious reasons. The “model” part of the design is the stuff that gets moved around by the controller and shown by the view. Think of a model as your arms or legs, and the view like your clothes. Your brain is the controller: it calls the shots, moves your arms and legs, and if everything goes right, the world sees a man (or woman) in clothing.
I’m going to reiterate something I said last time: if you want to entice web developers to write an app, they’re going to think like web developers. By and large, they aren’t going to be interested in patterns that aren’t portable.
This is Where We All Hug
What that means is that Angular gets to inherit some of the cool, some of the smart, and some of the practical from a number of different locations, and not reinvent the wheel in the name of being different. That sort of intentional re-use makes adoption easy.
Everything In the Right Place
There are three key organizational units in Angular, but that doesn’t really get started on the cool. The areas are Controllers, Services, and Directives, but the real value is in how they play together to make easy and intuitive blocks of code. Moreover, Angular comes with built-in directives that help you build MVC apps quickly and without a lot of drama.
It goes on from there to define a bunch more things the Document Controller might want to do. (And yes, you purists, it should be camel-case, but there was logic to the decision at the time). What it’s really doing is attaching functions to the $scope variable, which we’ll see in action in a little bit.
In order to get Angular working there are a couple short steps. First, include the directive “ng-app” on your HTML element like this:
Then attach a controller to some node of the html:
Now the Document Controller has access to any function or variable we assigned to the controller, and can “do” things inside that div tag. So for instance, when we load the page, we might tell the controller to go out to the internet and got a list of documents. Angular can loop through those documents to present them. It does that with its own built in Directives. In this case, the directive is “ng-repeat” and tells angular to use the “tr” tag as a template for every document in the list of documents. It makes for very readable code.
The astute observer will notice the “ng-click” directive as well: it does just what you think it does. “Edit” is a function that we put on the controller, and document is the same one we declared in the ng-repeat directive. In this case, “document” is the Model part of MVC: it got moved from the internet and shoved into the “clothes” of the HTML.
I don’t want to get into too much detail here, because the Angular tutorials are very good. Instead, I want to put this back in the context of WinJS.
Circling the Wagons
Angular does a great job of organizing code, but there’s a little bit of pain that it hides. See, the web is a big place, and it might take some time get that list of documents for the example above, or to get some search results back from your favorite search engine. Angular hides that by exposing a promise. See the example above where we defined the controller, and look for the “http.post” bit, followed by the “success” promise. Angular automatically keeps an eye on its own promises and follows up when the time comes. But what happens when Angular can’t detect that a promise has been fulfilled? The answer is “not much.”
WinJS has its own promise library, and it is used to do just about everything from reading from or writing to disk, to launching apps. But its promises are not Angular’s promises.
Think of it this way: if two friends promise to buy you a big mac when they get paid (and you trust your friends to buy you food), you might end up with a couple meals in a week, or a month, or both at the same time. They don’t have a built-in way to know about some other promise, whether it’s been kept, or that it exists at all. You might end up with two big macs at once, or no big macs for a very long time, or one and you don’t know who still owes you. You see the complications.
The folks at Angular anticipated the problem of external conditions and exposed the $scope.$apply() function. It tells angular that something has changed, and to check things out. It can accept a callback as an argument even, so it not only knows that something changed, but it actually executed the change itself, and is therefore aware of it. File IO is a pretty routine thing in a desktop app, so in WinJS you’ll see a lot of asynchronous calls to disk that return promises. Those WinJS promises are ok as long as they notify Angular that the promise is fulfilled. But you have to do it manually, and you have to do it all the time.
Exhale. I Promise This Coat Will Fit
I won’t pronounce myself an expert in WinJS or even in Angular because there’s always so much more to learn, but if you’re looking at putting together a solution in WinJS, drop me a line
Stay up to date with our email updates!