31 January 2017

I wasted a lot of time correctly defining angular modules. Here’s the problem and the solution.

Consider the following angular app:

<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script type="text/javascript">
    var myApp = angular.module('myApp', []);
    myApp.controller('MyController', ['$scope', function($scope) {  
        $scope.result = 'test';
    }]);
    var myApp2 = angular.module('myApp');
    myApp2.controller('MyController2', ['$scope','$window', function($scope,$window) {
        $scope.result2 = 'test2';
    }])
</script>
</head>
<body>
  <div ng-controller="MyController">
    {{result}}    
  </div>
  <div ng-controller="MyController2">
    {{result2}}
  </div>
</body>
</html>

While creating both myApp and myApp2 is redundant, it is used in this example because eventually MyController and MyController2 will be separated into two separate files.

If you change the line:

var myApp = angular.module('myApp', []);

to:

var myApp = angular.module('myApp');

or change the line:

var myApp2 = angular.module('myApp');

to:

var myApp2 = angular.module('myApp', []);

The example code will no longer work. If you look at the console, you may see the nomod error. In the description, it says that adding the empty array of dependencies to angular.module defines a new module of name myApp, and calling angular.module without that argument returns a reference to an existing module of name myApp.

In the first change, removing the empty array results in an error due to angular looking up a module that does not exist. In the second change, adding the empty array results in an error due to angular attempting to define a module that already exists.

This implementation is confusing to me - I think that angular should instead accept angular.module(‘appname’) without a second argument when there are no dependencies, and have a separate function for returning references to the module. If angular.module was called more than once, it could then return an error message that the module is already defined. However, I’m a newcomer to Javascript and angular so there’s probably a good reason it isn’t implemented this way that I’m unaware of.

This implementation means the developer must take care to know which dependencies are needed accross all controllers they wish to use, and also to make sure that the module is created first, and any subsequent controllers get attached to a reference, rather than re-defining the module.



blog comments powered by Disqus