Angular style guide - with Coffeescript?

A colleague found a guide, apparently from google here:

https://google-styleguide.googlecode.com/svn/trunk/angularjs-google-style.html

Reading this over, I have a few concerns based on my usage of angular of the last 6 months (I'm using Angular + Coffee in Rails, with the occasional Haml page):

  1. The doc seems to recommend using classes.

I've had a PITA dealing with code that relies on JS 'this' set to anything sane (which you'd leverage to invoke class method). This is especially painful in callbacks.

My work around was to make all my methods be tied to $scope, and ensure that all controller code resides in 1 lexical scope, e.g:

MyController = ($scope) ->
  $scope.my_callback= ->
    # do something useful, $scope is set to 'the right thing', and don't care about 'this'.

As opposed to the apparent recommendation of creating classes for controllers

class MyController
  constructor: (@$scope) ->

  callback: ->
    # @ is in the hands of the caller...

The coffee->JS produces:

var MyController;    
MyController = (function() {
  function MyController($scope) {
    this.$scope = $scope;
  }    
  MyController.prototype.callback = function() {};    
  return MyController;    
})();

Note that $scope is not in the lexical context of 'callback', which: a) means you have no hook to hang your hat on, and b) the coffeescript code is a bit confusing... if the method was not a class method, scope would have been in context :(

  1. Global names are promoted.

The doc seems to recommend using the google closure library goog.require/provide combo. While these are nice wrappers, they do effectively generate JS globals (with 'name spacing'). An alternative would be to wrap everything in a function (which in coffeescript land just involves putting things in a separate file), and only 'publish' the relevant items into angular as directives, services, controllers or what not. This avoids placing any globals into the JS namespace.

So... with all that said and done:

a) I can see controller == class being helpful in cases you have a controller class hierarchy, so you can use subclassing. But would you really do that? wouldn't you just factor out any common logic into a library or service. Is the pain around having 'this' ""float"" and not having '$scope' available worth it?

b) is there any reason to push controller/directive etc code into the global JS namespace?

(p.s not intending to star a religious war here, but I can live with that ;)

mm.. I battled with CoffeeScript classes in controllers for a while, but trying to learn Angular directives/scopes/etc at the same time was a recipe for disaster.. I didn't really have a definite need to use them so I gave up on it. Desty's recipe looks good, but I don't think the grunt run annotator I've got hooked up would deal with that format.

They do go very neatly into services though..

angular.module('app')

.factory 'AccountsService', (UserService, AccountsResource, UtilService, $log) ->
  new class
    constructor: ->
      @account = null
      @accounts = []

    save: (account) ->
      res = new AccountsResource(account)
      res.$save()

Using CoffeeScript's classes for Angular controller and services is a good idea, because of the clean and very readable code. Inheritance could be possible, but I've never tested it. You should not have problems with global variables if you initialize controllers and services in the Angular way.

Problems with this can typically be solved using the fat arrow => in CoffeeScript.

My controllers are looking like the following (while using controller as):

angular.module 'myapp.controller', []
.controller 'MyController', [ '$scope',
    class
        constructor: (@$scope) ->
            @attribute = null
            @$scope.$on 'anEvent', (event, data) => @attribute = data

        getValue: ->
            return @attribute
]