There’s a recent blog entry on the site about learning Angular. One aspect of it resonates with me:

“Quit jQuery for a While”

It’s true. You could well be used to having ‘on click’ equivalent event that mutate the DOM, and think that you could well mutate Angular models instead. That’s the path to more JavaScript than you need, and you’ll never know the low/no JavaScript idiomatic to Angular at entry-level.

I think of it this way: With Angular, model objects (POJOs) can drive views without JavaScript being involved. Similarly, views (via Angular’s expressions/bindings can drive models directly. You could make many applications with almost no JavaScript, and only add controller methods for the bits you cannot do with direct model <–> view interactions. In true Model View Controller, one model could drive more than one views, and all that magic.

An example

Story Navigator is many people’s work (including Miško Hevery the co-creator of Angular) over a few years:

With the AngularJS import commented out, you get to see the layout of the components of it:

The source for that page is here and the version with the commented out AngularJS import is here.

The running version is here and here for ‘Angular off’ version (more later on that).

How Much JavaScript?

Almost none, if you check the source. There are many lines of assignment as model objects are loaded from HTTP resource (xref.json) or created to support the view state. There’s really one function that handles the ‘click’ that would pop up the overlay. When we started the app, that was real Jquery overlay popup. Some time later we removed the Javascript (view the original diff) that would have placed the HTML in the DOM for that effect, and moved to Angular. Sure, we kept the HTML the JQuery-UI widget made, but we no longer needed JQuery. Anyway that is three lines of JavaScript now (lines 114 to 116), if we ignore the expressions that also manipulate the same model variables (ng-click on line 389)

You should follow the same process when you’re starting new Angular applications - minimize the amount of JavaScript you write, by directly tying models to views, and living with Angular’s idioms to effect that. When you encounter something you cannot do without JavaScript should you use it. That and when you find your Angular expression usage is hurting performance. Note - that’s when you find it hurting performance, and not when you think it may hurt performance in the future.

The document is the contract!

The document on the wire that is. The data loaded from the server for this UI, was already in a JSON structure that fitted it’s usage in the UI. The data in this app is readonly, but it could be as easy for you to make something that does GET/PUT for the same document after it is potentially modified in the UI. Thus, the document as it goes up and down in JSON form is a worthy discussion point for a team, if not a contract (without schema). If your project has Business Analysts, they can join in here. They may not understand how to code web-apps, but as they gaze at example documents they can make a judgement as to whether it is correct or not.

Component Omnipresence.

I’m drawn to a style of Angular that has all the potential rectangles in the page apparent at the same time, but conditionally hidden/shown with ng-hide and ng-show. Sure there are more advanced usages of Angular with externalized views and hidden templates, but I think early versions of an application are better without them, as a team comes up to speed with the style and idioms of Angular. You can see that component omnipresence with the Story Navigator fork (here is the link again). The app does not function in that form, but if the team were hit by a bus, a new team could acclimate quickly by cranking up the application with the AngularJS line turned off. You don’t get to see everything. Many of the expressions are hidden (being inside attributes), including ng-repeat stuff which would add a ton of clarity to the app.

Grouping your scoped variables.

Originally Story Navigator had many top-level variables in the $scope object. Now it is kinda grouped into three - constants (vars that never change), ui (vars the support the UI state) and data (the JSON resource that came over the wire).

The source again (var initialization - lines 68 to 111).

If nothing else, having the grouped allows you to shove them in the page quickly to aid debugging: { {ui | json}}.


May 19th, 2013