I'm so confused. AngularJS requires services, controllers, and directives to be created within Modules. But those services, controllers, and directives can be injected into any other service, controller, or directive REGARDLESS of the module they exist within! Correct? And, I haven't seen any IDEs or tools that care about the module names... other than ng-app. So, WHY create multiple modules? Does creating modules actually have a benefit other than read-ability within the source code?
Example...
(function(module) {
var dir = function(something) {
return {
};
};
module.directive("myDirective", dir);
}(angular.module("pointlessModuleName")));
I've tried finding the answer, but keep getting confused...
Multiple Module in Angularjs
I was thinking the exact same thing, and decided to walk on the wild side and merge everything under one module. Of course, only to find out a few minutes later why that was not a great idea :) So I'd like to take the time to explain where I think modules play a very nice role, independently from "the general opinion".
I started out with something along the lines of:
// main.js - v0
var ServerData = require('./services/server-data')
var filters = require('./filters')
angular.module('ServerLoad', ['ngRoute'])
.factory('ServerData', ['$http', ServerData])
.filter('lastseen', function () {return filters.lastseen})
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.otherwise({
redirectTo: '/servers'
})
}])
Now I wanted to add a view that presents a list of servers. A view, in essence, is not much more than a combination of a controller with a route, so I added those to the code. Here is what I got (and then I'll explain why this is not so nice and how a sub module solves that):
// main.js - v1
var ServerListView = require('./views/server-list-view') // <-- import view
var ServerData = require('./services/server-data')
var filters = require('./filters')
angular.module('ServerLoad', ['ngRoute'])
.factory('ServerData', ['$http', ServerData])
.controller('ServerListCtrl', ['ServerData', ServerListView]) // <-- add controller
.filter('lastseen', function () {return filters.lastseen})
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/servers', { // <-- add route
controller: 'ServerListCtrl', //
controllerAs: 'servers', //
templateUrl: 'assets/partials/server-list.html' //
}) //
.otherwise({
redirectTo: '/servers'
})
}])
Although this is certainly a valid set-up, what I don't like about it is that main.js
defines the controllerAs
and the templateUrl
properties. To me it feels these properties really ought to be defined where the code that depends on that is defined --- './views/server-list-view'
, maybe even on the ServerListView
class itself.
So, a bit in the same vein as your IIFE, I added a static method to ServerListView
to add the view to the module:
// main.js - v2 (from v0)
var ServerListView = require('./views/server-list-view') // <-- import view
// ...
angular.module('ServerLoad', ['ngRoute'])
// ...
ServerListView.setup(window.angular.module('ServerLoad')) // <-- adds ctrl and route
and
// server-list-view.js - v2
function ServerListView (ServerData) {
var scope = this
// ...
}
module.exports = ServerListView
ServerListView.setup = function (module) {
module
.controller('ServerListCtrl', ['ServerData', ServerListView])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/servers', {
controller: 'ServerListCtrl',
controllerAs: 'servers',
templateUrl: 'assets/partials/server-list.html'
})
}])
}
I thought this looked slightly better, but now the use of 'ServerData'
bothered me. After all, it wasn't declared in server-list-view.js
anywhere. Similarly, if the view would need some extra external module, I would have to edit main.js
to add it. That feels out of place.
Then it occurred to me that, if I can write an IIFE to take module
as argument, why not just let it take angular
as argument? Then it can define its own module however it pleases and include all dependencies needed. Moreover, if you're still fanatical about single-module-everything, then just use the 'ServerLoad'
module name and drop the dependency declaration. That is the only and whole difference!
// server-list-view.js - v3
// ...
ServerListView.setup = function (angular) {
angular.module('ServerLoad.ServerListView', ['ngRoute', 'ServerLoad'])
// ...
}
So, in conclusion, I think that the great advantage of using sub modules is not necessarily that others can reuse my code (I don't think anybody will ever be interested in my server list view), but that each bit of code can stand on its own, reusing other people's code, without requiring the main module to include all of that. The main.js
stays lean while the server-list-view.js
can pull in all sorts of stuff.
foot note. It still looks a bit odd having ServerLoad
as a dependency (to reach the ServerData
factory). In version 4 that factory will also live in its own sub module, of course ;-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With