AngularJS Patterns: Resolver as separate class

Use separate classes to resolve data. Use a powerful superclass.

by bjoerne

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular-route.js"></script>
<div>
    <div ng-view="true"></div>
</div>
<script type="text/ng-template" id="index.html">
    Hello, {{name}}!
</script>

CoffeeScript

class @ApplicationRouteProvider
    provide: ($routeProvider) ->
        $routeProvider.when '/',
            templateUrl: 'index.html'
            controller: ExampleCtrl
            resolve: ExampleResolver.resolve

class @BaseResolver

  constructor: (injectionNames, injectedObjects) ->
    @inject injectionNames, injectedObjects

  inject: (injectionNames, injectedObjects) ->
    i = 0
    for injectionName in injectionNames
      @[injectionName] = injectedObjects[i]
      i++

  resolve: ->
    @deferred = @$q.defer()
    @loadData()
    @deferred.promise

  loaded: (data) ->
    @deferred.resolve(data)

  loadingFailed: ->
    @deferred.reject()

  @injectedFunction: (injectionNames, factoryMethod) ->
    func = factoryMethod
    func.$inject = injectionNames
    func

class @ExampleResolver extends BaseResolver
    @$inject: ['$q']
    loadData: ->
        @loaded 'Superhero'
    @createInstanceAndResolve: ->
        resolver = new ExampleResolver(ExampleResolver.$inject, arguments)
        resolver.resolve()
    @resolve:
        name: @injectedFunction ExampleResolver.$inject, ExampleResolver.createInstanceAndResolve
    
class @ExampleCtrl
    constructor: ($scope, name) ->
        $scope.name = name

myApp = angular.module 'myApp', ['ngRoute']
myApp.config ['$routeProvider', new ApplicationRouteProvider().provide]
angular.bootstrap document, ['myApp']