<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[angular - Code of Serge]]></title><description><![CDATA[Throw enough spaghetti at the wall, maybe something will stick.]]></description><link>http://codeofserge.com/</link><generator>Ghost 0.5</generator><lastBuildDate>Thu, 10 Sep 2026 23:08:44 GMT</lastBuildDate><atom:link href="http://codeofserge.com/tag/angular/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[unit testing controller resolvers]]></title><description><![CDATA[<p>We all know the secret to responsive <a href="https://docs.angularjs.org/api/ngRoute/directive/ngView">ng-view</a>s, right?  Well, it isn't really a secret.  I am talking about routeProvder.when <a href="https://docs.angularjs.org/api/ngRoute/provider/$routeProvider">resolvers</a> for pre-loading asynchronous server data. You really don't want your view sitting empty.</p>

<blockquote>
  <p>resolve - {Object.&lt; string, function >=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired. If any of the promises are rejected the $routeChangeError event is fired. The map object is:
  - key – {string}: a name of a dependency to be injected into the controller.
  - factory - {string|function}: If string then it is an alias for a service. Otherwise if function, then it is injected and the return value is treated as the dependency. If the result is a promise, it is resolved before its value is injected into the controller. Be aware that ngRoute.$routeParams will still refer to the previous route within these resolve functions. Use $route.current.params to access the new route parameters, instead.</p>
</blockquote>

<p>Ok, great: we have a factory function for getting some stuff from the server. On a route call to /Home, the resolver function returns some data. <em>(This data can be a promise, in which case the promise will first be resolved before the controller is instantiated.)</em></p>

<pre><code class="language-javascript">(function(angular) {
    'use strict';

    var app = angular.module('app', ['ngRoute']).config([
        '$routeProvider',
        function($routeProvider) {
            $routeProvider.when('/Home/:message?', {
                templateUrl: 'Home.html',
                controller: 'home',
                resolve: {
                    data: ['$route', function ($route) {
                        return "Test String Data" + $route.current.params.message;
                    }]
                }
            }).otherwise({redirectTo: '/Home'});
        }
    ]);

    app.controller('home', [
        "$scope",
        "data",
        function($scope, data) {
            $scope.message = data;
        }
    ]);
})(window.angular);
</code></pre>

<p>But now I have business logic in my configurations. Routing files, in my mind, are a configuration item and should not actually contain code. Keep in mind that your resolver factory function is also injectable, as the example injects $route. As a result, it can actually contain some pretty complicated business logic for looking up records. Let's take a look at an example that pulls from the server, and join the server information with some request message.</p>

<pre><code class="language-javascript">resolve : {  
  data : ['$route', '$http', '$q', function($route, $http, $q) {
      var deffer = $q.defer();
      $http.get('/Data').then(function(result){
          deffer.resolve([result.data.Value, $route.current.params.message].join(' '));
      });

      return deffer.promise;
  }]
}
</code></pre>

<p>It is easy to see that, even with such a small function, we now might want to look into doing some type of unit testing. But right now, the resolver is just an anonymous function--unless you bootstrap the whole angular stack and your http, which is doable, but does make the first <strong>"it"</strong> more difficult. So can we handle this in a slightly simpler manner? Just move the resolver factory function to where it can be unit tested.</p>

<pre><code class="language-javascript">app.provider('data', function () {  
        return {
            $get: function () {
                return {
                    home: [
                        '$route',
                        '$http',
                        '$q',
                        function ($route, $http, $q) {
                            var deffer = $q.defer();
                            $http.get('/Data').then(function (result) {
                                deffer.resolve([result.data.value, $route.current.params.message].join(' '));
                            });

                            return deffer.promise;
                        }
                    ]
                }
            }
        }
    });
</code></pre>

<p>And now that the resolver function exists as an artifact of a provider, we can expose it inside the config function.</p>

<pre><code class="language-javascript">var app = angular.module('app', ['ngRoute']).config([  
    '$routeProvider',
    'dataProvider',
    function ($routeProvider, dataProvider) {
        var data = dataProvider.$get();
        $routeProvider.when('/Home/:message?', {
            templateUrl: 'Home.html',
            controller: 'home',
            resolve: {
                data: data.home
            }
        }).otherwise({ redirectTo: '/Home' });
    }
]);
</code></pre>

<p><strong>To The Unit Test</strong></p>

<p>So far, we have made the resolver factory named instead of anonymous. But the holy grail here is really the unit test of the resolver function. The full source code can be found <a href="https://github.com/SergeiGolos/CodeOfSerge/blob/master/angular-unit-tesing-controller-resolvers/Content/test/app.test.js">here</a>  but the meat and potatoes is outlined in the test here. Variables prefixed with _ are, in this case, different mocks.</p>

<pre><code class="language-javascript">it('The the promise resolves to a combination of the get results and route messages', function() {  
    var result = fn(_route, _http, _q);
    expect(angular.isFunction(result.then)).toBe(true);
    result.then(function(data) {
        expect(data).toBe('test test');
    });

    _timeout.flush();
});
</code></pre>

<p>The result of <em>"test test"</em> matches the mock data being returned form the _http and _route mock objects. Naturally, this example is simplified. However, I have also done some work in which complicated async logic was executed in these functions.</p>

<p><strong>Conclution</strong></p>

<p>It isn't a big change to wrap the resolver function inside a provider, and the benefit of being able to test a pretty vital part of the applications is significant. We also gain the ability to re-use this resolver code since multiple resolvers can be used for a single route.</p>]]></description><link>http://codeofserge.com/unit-testing-controller-resolvers/</link><guid isPermaLink="false">755e964a-6f10-4c71-b509-249f549e7d47</guid><category><![CDATA[angular]]></category><category><![CDATA[unit testing]]></category><dc:creator><![CDATA[Sergei Golos]]></dc:creator><pubDate>Sat, 28 Feb 2015 22:12:32 GMT</pubDate></item><item><title><![CDATA[@script, annotation and angular 1.x]]></title><description><![CDATA[<p><code>Note, this post has been edited on 12/11/2014 and 01/12/2015.  These changes were made to keep the code base changes to handle routing and directives.</code></p>

<p>A previous <a href="http://codeofserge.azurewebsites.net/script-annotation-for-the-win/">post</a> talked about a general idea behind data annotation and the ability to mark up classes. But the example was far from being real world or useful.  Today we are going to explore the way that data annotation can be used to decouple business logic with angular bindings.  We are in search of a simpler solution to ES6 modules or RequireJS and Angular modules.</p>

<p><strong>Module Pattern and Angular</strong></p>

<p>ES6 brings us modules and the "import" keyword for better composition management, which basically means that this code:</p>

<pre><code class="language-javascript">import {ngBase} from './ngBase';  
</code></pre>

<p>transforms into RequireJS code that creates a dependency and on './ngBase</p>

<pre><code class="language-javascript">define(['./ngBase'], function($__0) {  
  "use strict";
  if (!$__0 || !$__0.__esModule)
  $__0 = {default: $__0};
  var ngBase = $__0.ngBase;
});
</code></pre>

<p>Nicely enough, ngBase becomes the variable into which the import is piped, scoped to the wrapper function. So how does this play with something like Angular which has its module system. A quick look online brings about a general consensus that the module pattern is good for business logic, but the angular bootstrapping should take place once the require js modules are loaded.</p>

<ul>
<li><a href="http://www.sitepoint.com/using-requirejs-angularjs-applications/">http://www.sitepoint.com/using-requirejs-angularjs-applications/</a></li>
<li><a href="http://solutionoptimist.com/2013/09/30/requirejs-angularjs-dependency-injection/">http://solutionoptimist.com/2013/09/30/requirejs-angularjs-dependency-injection/</a></li>
<li><a href="http://marcoslin.github.io/angularAMD/#/home">http://marcoslin.github.io/angularAMD/#/home</a></li>
<li><a href="http://stackoverflow.com/questions/12529083/does-it-make-sense-to-use-require-js-with-angular-js">http://stackoverflow.com/questions/12529083/does-it-make-sense-to-use-require-js-with-angular-js</a></li>
</ul>

<p>Each of these post talks about creating non-angular aware modules that are later bootstrapped in another bootstrapping file. In my mind, this is a bit messy.  When anything changes, you must change the bootstrapping file and the implementation file logic. But data annotation solves this problem. We can defer bootstrapping by marking our classes with all required data annotations to complete the late bootstrapping.</p>

<p><strong>Annotate it All</strong></p>

<p>So data annotation lets us create classes that understand their own purpose. Ideally, anything in Angular can be broken down into a class constructor function with annotation that defines the class function.</p>

<p>We annotate the controller/factory/directive name and dependency list into the ngController/ngFactory/ngDirective and ngInject annotation.</p>

<p><strong>Annotation Classes</strong></p>

<p>The magic behind this type of annotation is a collection of annotation classes that can register the class it annotates against an angular module.</p>

<p><a href="https://github.com/SergeiGolos/CodeOfSerge/blob/master/script-annotation-and-angular-1x/src/lib/ngBase.ats">ngBase</a> class is an abstract that all Angular-based annotations derive from. We do have a useful <em>wrap</em> function, which allows us to wrap the Angular array notation for dependency injection. The ngBase class is common ground for all Angular annotations from Angular registering functions (ngController/ngFactory/ngDirective).</p>

<p><a href="https://github.com/SergeiGolos/CodeOfSerge/blob/master/script-annotation-and-angular-1x/src/lib/ngController.ats">ngController</a> class is an actual annotation class. It describes controllers to angular modules. The register function, which is aware of annotation on the class, can work in combination with other annotations like route and inject. The controller annotation simply takes the name.</p>

<pre><code class="language-javascript">@ngController('main')
@ngInject(['$scope', 'data'])
@ngRoute('/Home', { templateUrl : 'home.html' });

export class main {  
  constructor($scope, data) {
    $scope.data = data();
  }
}
</code></pre>

<p><a href="https://github.com/SergeiGolos/CodeOfSerge/blob/master/script-annotation-and-angular-1x/src/lib/ngFactory.ats">ngFactory</a> annotation class for creating factories, the Angular version of a singleton.  Like ngController, it also works in combination with</p>

<pre><code class="language-javascript">@ngFactory('data')

export class data {  
  constructor() {
    return () =&gt; "test";
  }
}
</code></pre>

<p><a href="https://github.com/SergeiGolos/CodeOfSerge/blob/master/script-annotation-and-angular-1x/src/lib/ngDirective.ats">ngDirective</a> annotation class for creating directives has some additional logic. Like the other ngBase classes the name of the directive is the first argument of the annotation constructor and the directive property object as the second argument. The constructor of the annotated class automatically becomes the link function on the directive object.</p>

<pre><code class="language-javascript">@ngDirective('hello', {
  scope : true,
  template : '&lt;div&gt; hello {{data}}&lt;/div&gt;',
  restrict : 'AE'
})
@ngInject(['data'])
export class hello {  
  constructor(data) {
    return (scope, element, attr) =&gt; {
      scope.data = data();
    }
  }
}
</code></pre>

<p><strong>The Bootstrapper</strong></p>

<p>Annotations can bind behavior to a class, and we can process the behavior by looking at injectable dependencies. The <a href="https://github.com/SergeiGolos/CodeOfSerge/blob/master/script-annotation-and-angular-1x/src/lib/ngBootstrap.ats">ngBootstrap</a> class processes a list of imports. In our bootstrapping process, this is denoted by arguments based on how Tracuer transpiles this code.</p>

<pre><code class="language-javascript">import {ngBootstrap} from './lib/ngBootstrap';  
import {data} from './data';  
import {main} from './main';  
import {hello} from './hello';

var app = ngBootstrap(document, angular.module('test', []), arguments);  
</code></pre>

<p>Transpiled, we get this code, which explains the argument's object.</p>

<pre><code class="language-javascript">define(['./lib/ngBootstrap', './data', './main', './main2', './hello'], function($__0,$__2,$__4,$__6,$__8) {  
  "use strict";
  if (!$__0 || !$__0.__esModule)
  $__0 = {default: $__0};
  if (!$__2 || !$__2.__esModule)
  $__2 = {default: $__2};
  if (!$__4 || !$__4.__esModule)
  $__4 = {default: $__4};
  if (!$__6 || !$__6.__esModule)
  $__6 = {default: $__6};
  if (!$__8 || !$__8.__esModule)
  $__8 = {default: $__8};
  var ngBootstrap = $__0.ngBootstrap;
  var data = $__2.data;
  var main = $__4.main;
  var main2 = $__6.main2;
  var hello = $__8.hello;
  var app = angular.module('test', ['ngRoute']);
  ngBootstrap(document, app, arguments);
  return {};
});
</code></pre>

<p><strong>Conclusion</strong></p>

<p>You can find running code examples <a href="https://github.com/SergeiGolos/CodeOfSerge/tree/master/script-annotation-and-angular-1x">here</a></p>

<p>This post gave a real world example of the usefulness of data annotation. But there is a lot more. There are benefits to decoupling the application from Angular. The annotation can be quickly re-writen to bind a different framework to your current classes. There are benefits to unit testing a directive without needing to bind to angular.</p>

<p>Overall, data annotation is a tool for the tool box, and more posts will come on how this tool is useful.</p>]]></description><link>http://codeofserge.com/script-annotation-and-angular-1x/</link><guid isPermaLink="false">3d028ba6-63c5-41b8-a56f-10123a34b34e</guid><category><![CDATA[@script]]></category><category><![CDATA[annotation]]></category><category><![CDATA[angular]]></category><category><![CDATA[requirejs]]></category><dc:creator><![CDATA[Sergei Golos]]></dc:creator><pubDate>Tue, 13 Jan 2015 03:20:00 GMT</pubDate></item></channel></rss>