AngularJS best practices for module declaration? - angularjs

I have a bunch of Angular modules declared in my app. I originally started declaring them using the "chained" syntax like this:
angular.module('mymodule', [])
.controller('myctrl', ['dep1', function(dep1){ ... }])
.service('myservice', ['dep2', function(dep2){ ... }])
... // more here
But I decided that wasn't very easy to read, so I started declaring them using a module variable like this:
var mod = angular.module('mymodule', []);
mod.controller('myctrl', ['dep1', function(dep1){ ... }]);
mod.service('myservice', ['dep2', function(dep2){ ... }]);
...
The second syntax seems a lot more readable to me, but my only complaint is that this syntax leaves the mod variable out in the global scope. If I ever have some other variable named mod, it would be overridden with this next one (and other issues associated with global variables).
So my question is, is this the best way? Or would it be better to do something like this?:
(function(){
var mod = angular.module('mymod', []);
mod.controller('myctrl', ['dep1', function(dep1){ ... }]);
mod.service('myservice', ['dep2', function(dep2){ ... }]);
...
})();
Or does it even matter enough to care? Just curious to know what the "best practices" are for module declaration.

'Best' way to declare a module
As angular is on the global scope itself and modules are saved to its variable you can access modules via angular.module('mymod'):
// one file
// NOTE: the immediately invoked function expression
// is used to exemplify different files and is not required
(function(){
// declaring the module in one file / anonymous function
// (only pass a second parameter THIS ONE TIME as a redecleration creates bugs
// which are very hard to dedect)
angular.module('mymod', []);
})();
// another file and/or another anonymous function
(function(){
// using the function form of use-strict...
"use strict";
// accessing the module in another.
// this can be done by calling angular.module without the []-brackets
angular.module('mymod')
.controller('myctrl', ['dep1', function(dep1){
//..
}])
// appending another service/controller/filter etc to the same module-call inside the same file
.service('myservice', ['dep2', function(dep2){
//...
}]);
// you can of course use angular.module('mymod') here as well
angular.module('mymod').controller('anothermyctrl', ['dep1', function(dep1){
//..
}])
})();
No other global variables are required.
Of course it depends all on preferences, but I think this is kind of the best practise, as
you don't have to pollute the global scope
you can access your modules everywhere and sort them and their functions into different files at will
you can use the function-form of "use strict";
the loading order of files does not matter as much
Options for sorting your modules and files
This way of declaring and accessing modules makes you very flexible. You can sort modules via function-type (like described in another answer) or via route, e.g.:
/******** sorting by route **********/
angular.module('home')...
angular.module('another-route')...
angular.module('shared')...
How you sort it in the end is a matter of personal taste and the scale and type of the project. I personally like to group all files of a module inside of the same folder (ordered into sub-folders of directives, controllers, services and filters), including all different test-files, as it makes your modules more reusable. Thus in middle-sized projects I end up with a base-module, which includes all basic routes and their controllers, services, directives and more or less complex sub-modules, when I think they could be useful for other projects as well,e.g.:
/******** modularizing feature-sets **********/
/controllers
/directives
/filters
/services
/my-map-sub-module
/my-map-sub-module/controllers
/my-map-sub-module/services
app.js
...
angular.module('app', [
'app.directives',
'app.filters',
'app.controllers',
'app.services',
'myMapSubModule'
]);
angular.module('myMapSubModule',[
'myMapSubModule.controllers',
'myMapSubModule.services',
// only if they are specific to the module
'myMapSubModule.directives',
'myMapSubModule.filters'
]);
For very big projects, I sometimes end up grouping modules by routes, as described above or by some selected main routes or a even a combination of routes and some selected components, but it really depends.
EDIT:
Just because it is related and I ran into that very recently again: Take good care that you create a module only once (by adding a second parameter to the angular.module-function). This will mess up your application and can be very hard to detect.
2015 EDIT on sorting modules:
One and a half year of angular-experience later, I can add that the benefits from using differently named modules within your app are somewhat limited as AMD still does not really work well with Angular and services, directives and filters are globally available inside the angular context anyway (as exemplified here). There is still a semantic and structural benefit though and it might be helpful being able to include/ exclude a module with a single line of code commented in or out.
It also almost never makes much sense to separate sub-modules by type (eg. 'myMapSubModule.controllers') as they usually depend on each other.

I love the angular-styleguide by Johnpapa, and here are some rules that related to this question:
Rule: Named vs Anonymous Functions
Avoid using anonymous functions:
// dashboard.js
angular
.module('app')
.controller('Dashboard', function() { })
Instead, use named functions:
// dashboard.js
angular
.module('app')
.controller('Dashboard', Dashboard);
function Dashboard() { }
As the author says: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code.
Rule : Define 1 component per file.
Avoid multiple components in one file:
angular
.module('app', ['ngRoute'])
.controller('SomeController', SomeController)
.factory('someFactory', someFactory);
function SomeController() { }
function someFactory() { }
Intead, use one file to define the module:
// app.module.js
angular
.module('app', ['ngRoute']);
one file just uses the module to define a component
// someController.js
angular
.module('app')
.controller('SomeController', SomeController);
function SomeController() { }
and another file to define another component
// someFactory.js
angular
.module('app')
.factory('someFactory', someFactory);
function someFactory() { }
Of course, there are many other rules for modules, controllers and services that are quite useful and worth reading.
And thanks to comment of ya_dimon, the above code should be wrapped in IIFE, for example:
(function (window, angular) {
angular.module('app')
.controller('Dashboard', function () { });
})(window, window.angular);

I recently had this conundrum as well. I had started off just like you using the chained syntax, but in the long run it becomes unwieldy with large projects. Normally I'd create a controllers module, a services module and so on in separate files and inject them into my main application module found in another file. For Example:
// My Controllers File
angular.module('my-controllers',[])
.controller('oneCtrl',[...])
.controller('twoCtrl',[...]);
// My Services File
angular.module('my-services',[])
.factory('oneSrc',[...])
.facotry('twoSrc',[...]);
// My Directives File
angular.module('my-directives',[])
.directive('oneDrct',[...])
.directive('twoDrct',[...]);
// My Main Application File
angular.module('my-app',['my-controllers','my-services','my-directives',...]);
But each one of these files was getting way to large as the project grew. So I decided to break them up into separate files based on each controller or service. I found that using angular.module('mod-name'). without the injection array, is what you need for this to work. Declaring a global variable in one file and expecting that to be readily available in another just doesn't work or could have unexpected results.
So in short my application looked something like this:
// Main Controller File
angular.module('my-controllers',[]);
// Controller One File
angular.module('my-controllers').controller('oneCtrl',[...]);
//Controller Two File
angular.module('my-controllers').controller('twoCtrl',[...]);
I did this to the services file as well, no need to change the main application module file you'd still be injecting the same modules into that.

One other practice is to stuff controllers, directives, etc in their own modules and inject those modules into your "main" one:
angular.module('app.controllers', [])
.controller('controller1', ['$scope', function (scope) {
scope.name = "USER!";
}]);
angular.module('app.directives', [])
.directive('myDirective', [function () {
return {
restrict: 'A',
template: '<div>my directive!</div>'
}
}]);
angular.module('app', [
'app.controllers',
'app.directives'
]);
Nothing is left in the global scope.
http://plnkr.co/edit/EtzzPRyxWT1MkhK7KcLo?p=preview

I like to divide my files and my modules.
Something like this:
app.js
var myApp = angular.module('myApp', ['myApp.controllers', 'myApp.directives', 'myApp.services']);
myApp.config(['$routeProvider', function($routeProvider) {
/* routes configs */
$routeProvider.when(/*...*/);
}]);
directives.js
var myDirectives = angular.module('myApp.directives', []);
myDirectives.directive( /* ... */ );
service.js
var myServices = angular.module('myApp.services', []);
myServices.factory( /* ... */ );
Im not a big fan of the "chained style", so I prefer to write down my variable always.

I suggest to follow Angularjs Style Guide.
They handle all concept from naming convention, to modularize your app and so on.
For angular 2, you can check Angular 2 Style Guide

For me, chaining is the most compact way:
angular.module("mod1",["mod1.submod1"])
.value("myValues", {
...
})
.factory("myFactory", function(myValues){
...
})
.controller("MainCtrl", function($scope){
// when using "Ctrl as" syntax
var MC = this;
MC.data = ...;
})
;
That way I can easily move components between modules, never need to declare the same module twice, never need any global variables.
And if the file gets too long, solution is simple - split into two files, each declaring its own module at the top. For more transparency, I try to keep one unique module per file and name it resembling the full path of the file. This way also I never need to write a module without [], which is a common pain point.

Related

Exporting/Importing AngularJS Controllers, Directives, Factories, Services with Webpack 4

I managed to migrate our AngularjS 1.3.15 project from Gulp to Webpack 4, and now I'm trying to organize all our huge 5000+ line files into separate files. The problem is that I have no idea how exactly to export an AngularJS controller or directive etc. as to be easily imported into an index.js file, so that can be imported to our main.js file.
Example, one of our huge files starts with the angular.module and then a controller, like this:
(function () {
angular.module('AppName', ['app.services'])
.controller('SomeCtrl', ['Session', 'Api', '$scope',
function (Session, Api, $scope) {
let init = function () {
console.log('Stuff');
};
init();
}])
This is then followed by a factory:
.factory('GlobalChart', [function () {
let self = this;
self.containerWidth = 210;
self.containerHeight = 210;
self.width = 150;
self.height = 150;
self.radius = Math.min(self.width, self.height) / 2;
return this;
}])
Followed by a directive:
.directive('reportTopbar', ['$window',
function ($window) {
return {
templateUrl: 'views/someview.html?v=' + GLOBAL_VERSION,
transclude: false,
scope: {
data: '='
},
link: function (scope, element, attrs, ctrl) {
// code here
},
};
}])
Following this last example there's just a bunch of directives, and everything is in this huge file, hence the need to organize this so that it's maintainable.
So what exactly would be the correct way to export all these?
Start by examining what you have.
The angular.module call returns an object, but in your implementation, you are ignoring the result (not storing it). You are instead chaining the calls to .controller, .directive, etc. onto this anonymous object.
One possible way to solve this would be to store the return value of the module call (i.e. var app = angular.module(....)), which can be exported. Then, in each of your other calls, you can chain on the stored value (app.directive(...)), which then makes each of these calls separable from the main code file, and potentially exportable.
This is method would be the most direct way to solve your immediate problem, since it would only require declaring a variable and then referencing the variable throughout your code. However it would not be the most optimal solution.
Another possible way would be to declare each of your controllers, factories, directives, etc. as functions, and chain them onto the angular module by name.
This also brings up another topic where you could improve the functionality and readability of the code: Dependency Injection. You can use $inject instead of inline Dependency Declarations, to make future imports and minification of the code much cleaner.
For example:
angular.module('AppName', ['app.services'])
.controller('SomeCtrl', SomeCtrl);
SomeCtrl.$inject = ['Session', 'Api', '$scope'];
function SomeCtrl(Session, Api, $scope) {
...
}
Now, you can export a single file with the Angular Module Definition and all of the controllers, factories, directives, etc. declared together, in an easily identifiable place. All of the individual functions can then be exported as needed in their own files, keeping the code clear, clean, and readable.
These tips (and many others) are covered in John Papa's Style Guide. This guide is a must read for anyone serious about optimizing their AngularJs code.

Injecting module function into AngularJS service

I have been reading these two links 1 and enter link description here. The idea is to have clean and module code.
The modular approach explained in the links above suggest to a file for the function, and another file for injecting the functions into angular's directive, controller, ... .
As an example:
/* app.js */
define([
'/path/to/controller',
'/path/to/service1'
], function(MyController, MyService1))
{
"use strict";
angular
.module('myApp', [])
.controller('MyController', MyController)
.factory('MyService1', MyService1);
});
/* controller */
define(function()
{
"use strict";
return ['$scope', 'MyService1', MyController];
function MyController($scope, MyService1)
{
/* Now do your coding here */
}
});
/* service */
// Identical to controller
Notice here how the function is implemented in one file, and then injected into the angular.
Now, I can see a potential problem is your service custom depends on another custom service. Say MyService2 also uses MyService1. My two services now look like:
/* MyService1 */
define(function() {
return MyService1;
function MyService1() {
/* Code Here */
}
});
/* MyService2 */
define(function() {
return ['MyService1', MyService2];
function MyService2(MyService1) {
/* This uses MyService1 here */
}
});
If your app uses both, then all is well, however, if it only uses one, then we have a problem:
/* This will work fine */
angular
.module('myApp')
.controller('MyController', MyController)
.factory('MyService1', MyService1)
.factory('MyService2', MyService2);
/* This will NOT */
angular
.module('myApp')
.controller('MyController', MyController)
.factory('MyService2', MyService2); <-- This guy internally requires MyServce1
I don't see how to solve this problem while still keeping this kind of approach. Can you help?
RequireJS and AngularJS have two non-overlapping dependency resolution mechanisms. If you're really going to use both, as suggested in the linked guide (I'm hard-pressed to imagine a scenario where this would be useful enough), you need to keep in mind, that the individual "service files" don't really contain services at all. They contain just their constructors/factories. To put it all together, your module definition needs to solve both of the separate concerns:
load all files with the constructors/factories needed for service/controller/... definitions, and
define all things that you don't want to leave as external dependencies.
In other words, if you define a module containing just service2, which has a service1 dependency, and don't define service1, then service1 becomes an external dependency of your module (it cannot be used in an environment where no service1 is defined).
In other words, the two DI frameworks do NOT complement each other so that you could load a file containing a service only when you need to inject it (in Angular) for the first time. You could find a way to use RequireJS to load something (most likely whole separate Angular applications) on demand. But you cannot load a service/controller/... on demand (at runtime), because such things can only be defined in the configuration phase of AngularJS application construction. Once the run phase starts, no more configuration (e.g. service definition) can be done.
If you just want to create a single application with modular code, I'd suggest that you leave RequireJS be for now and focus on simply creating modular code, as the style guide suggests.
i see you use requirejs there so you got 2 dependencies frameworks in parallel (angular and requirejs)
when you define a file that has a dependency on MyService2, than MyService2 needs to define a dependency to MyService1 (requirejs dependency) so both files are loaded and available.
that closes the issue for requirejs file loading.
now angular: in MyService1 you do
angular.factory('MyService1', function () {....});
than angular knows of that service and can inject it to anyone who needs it.
for MyService2 you do,
angular.factory('MyService2', ['MyService1', function(MyService1) {...}]).
and now angular injected MyService1 into MyService2 and you can use it in service 1.
than in some controller you need service 2 you just do
angular.controller('MyController', ['MyService2', function(MyService2){...}]);
and angular injects service 2 that has already service 1 injected into it.

AngularJS controller and service creation

Im working on a new Angular project with the following files:
//app.js
var mainApp = angular.module('mainApp', ['serviceA', 'serviceB', "ctrlA", 'ctrlB']);
//ctrlA.js
var ctlA = angular.module('serviceA', []);
ctlA.controller('menuController', ['$scope', 'serviceA', function($scope, serviceA) {
// ...
}]);
Is there a reason not to do it this way ?
//ctrlB.js
angular.module('mainApp')
.controller('ctrlB', ['$scope', 'serviceA', function($scope, serviceA) {
// ...
}]);
What Zenorbi, mentioned is absolutely right. However, thought of adding this information to conclude a better answer.
You can modularize the app into multiple segments to make it easy to understand. The segmentation can be
done in different ways.
Based on service types - this will be useful for small applications
var mainApp = angular.module('mainApp', [
'app.controllers', // Controllers
'app.directives', // Directives
'app.filters', // Filters
'app.services' // Services
]);
Example implementation of a module.
var ctrls = angular.module('app.controllers');
ctrls.controller('menuController', ['$scope', 'serviceA', function($scope, serviceA) {
// ...
}]);
According to the purpose of each module. For example, you can separate chart related classes to a separate module and isolate it from the main code base. This will allow parallel programming by someone else, as this module can act independent from the parent module.
Both implementations are valid, but the module system is there to make sure you separate a bigger application into modules. If serviceA, serviceB, ctrlA and ctrlB are closely related, you might as well bundle them into a module. If you want to have your services elsewhere, you may create a module called mainApp.services.
It is up to you, how you structure the code, but modules exist for a reason. To have more than one "thing" in them.

How do I correctly split angularjs module controllers/services/etc into their own files?

I've seen some projects keep all the "pieces" (controllers/services/directives) to a module in one file. angular-app does it like that.
example:
angular.module('myModule', ['depA', 'depB'])
.controller('MyController', function() {})
.service('myService', function() {});
However I've worked on teams in the past on large angular projects where individual controllers/services/directives were kept in their own files. I like the idea of keeping them in their own files to keep the files small among other reasons. The problem now is that I'm the one in charge of getting the beginning pieces and build process put together. All I had to do before was write application code and follow the standard on those projects.
In order to have separate files properly, I believe I would have to have one main module file.
example:
// file 1
angular.module('myModule', ['depA', 'depB']);
// file 2
angular.module('myModule')
.controller('MyController', function() {});
So my question is, what file loading order do I need to make sure happens? Do I only need to make sure that the main module file (file 1) is loaded before file 2?
That seems odd to me. If there was also a service file attached to the previously mentioned module and the controller file 2 was already loaded, but the service file wasn't yet, isn't it possible that angular could invoke that controller file and then eventually cause things to get out of whack?
Also, if you think I'm handling this the wrong way I would love to hear your suggestions.
Module Load Order
Just make sure that when you register a new module, by the time your application bootstraps, it's module dependencies should have already been loaded by the browser.
So anytime you do this:
angular.module('myApp', ['dep1', 'dep2', 'dep3']);
The files with dep1, dep2, and dep3 should have already been loaded by the time your application bootstraps.
If you are using <script> tags and automatic bootstrapping (the angular default) then the order of your <script> tags shouldn't matter. However, if using a library like requirejs make sure that all of your dependencies are loaded before manually bootstrapping.
Additional Considerations
As long as your modules are loaded in the correct order, then..
There is no need to worry about the order of controllers, directives, services, factories, providers, constants, or values
The order of run blocks may be important only as they relate to other run blocks since they are executed in the order in which they are registered (within a specific module).
The order of config blocks may be important only as they relate to other config blocks since they are executed in the order in which they are registered (within a specific module).
In regards to the prior 2 points, the order of dependencies (for example ['dep1', 'dep2', 'dep3'] vs ['dep2', 'dep3', 'dep1']) will also effect the order of execution of run blocks and config blocks. Angular will traverse the dependency tree twice and execute, in order, all config blocks followed by all run blocks.
Angular uses a post-order traversal to initialize modules and their associated config and run blocks. So if we represent our module dependencies as a tree:
The order of traversal is ACEDBHIGF
What I do on my projects, is keep everything separate in the developing environment, but then compile things down via gulp.js (grunt should work as well). That's a separate subject though, but here's an example of how to keep your angular code in different files.
The main file (must be loaded first) could be as follows. We will define our module, controllers, directives, repositories, or whatever else. Let's call it app.js:
// AngularJS Application File
var example = angular.module(
// ngApp name
'example',
// Default Dependencies
[
'exampleControllers',
'exampleRepositories',
'exampleDirectives'
]
);
var exampleControllers = angular.module('exampleControllers', []);
var exampleRepositories = angular.module('exampleRepositories', []);
var exampleDirectives = angular.module('exampleDirectives', []);
Now, we can access this exampleControllers, exampleRepositories, and exampleDirectives from within any javascript file that follows.
controllers.js file.
exampleControllers
// Main Controller
.controller('MainController',
[
'$scope',
'$log',
function ($scope, $log) {
$scope.hello = 'Hello World';
}
]
)
// Sub Page Controller
.controller('SubPageController',
[
'$scope',
'someService',
'$log',
function ($scope, sService, $log) {
$log.info($scope.hello);
}
]
);
anothercontroller.js file:
exampleControllers
// Another Controller
.controller('AnotherController',
[
'$scope',
'$log',
function ($scope, $log) {
$scope.helloagain = 'Hello World, from another controller';
}
]
)
And so forth.. Just make sure your app.js file gets loaded first so the example<whatever> variables are available.
I would definitely read up on gulp.js (http://gulpjs.com/). It's pretty awesome for automating work flows.

declare module for each file or use the app module for all files?

I started learning angularjs and I see 2 types of module uses and I cant understand when to use this and when this:
example1:
var app = angular.module('app', []);
app.factory('Comment', function($http) {
}
app.controller('mainController', function($scope, $http, Comment) {
}
or
example2:
angular.module('commentService', [])
.factory('Comment', function($http) {
}
angular.module('mainCtrl', [])
.controller('mainController', function($scope, $http, Comment) {
}
var app = angular.module('app', ['commentService','mainCtrl']);
sometimes I see module declarion in each file(services factory controllers and so on)
and sometimes I see using the app module in those files, what is the right way? and why both of them works?
First and foremost, if you're concerned about app organization, read the discussion on the yeoman-generator-angular issue board from about a year ago. There's way more wisdom there than you could feasibly expect to get in a SO answer.That said, I'll try to provide an answer that's more pertinent to your specific concern, and (marginally) more concise.
DO NOT make a module for a single controller like angular.module('MainCtrl',[]).controller('MainCtrl'), or even a set of controllers who are only related in that they are all controllers:
angular.module('appCtrl', [])
.controller('appleController', function ($scope) {})
.controller('orangeController', function ($scope) {})
.controller('unicornController', function ($scope) {})
;
Why is this a bad idea? First, by definition, it's categorical, not modular; modules are groupings of system components which are related topically, not conceptually. When you're building a car, you don't put in all of the nuts and bolts at once. You put in the nuts and bolts that hold together the module that you're building. Controllers are like nuts and bolts. An engine is like a module.
Second, now you have to inject the appCtrl module anywhere that you want access to a controller. That's just a mess for developers to have to deal with; they're always digging through the code trying to find "whatever that module with that one thing in it" was, or they'll just repeat code all over the place.
Dependency Injection in AngularJS is less a rule than a (clever and awesome) string manipulation hack, and JavaScript has no "namespacing" system in the classical sense. Creating modules like app.products or app.cart is more for the developer's convenience and/or controlling the release cycle than making the program "work".
For these and other reasons, I caution developers against "Premature Modularization". If you're writing something app-specific---that is, you won't be reusing it right now in another app---why not just attach it to your app module? Then you have access to it anywhere in your app that you want it. (There are of course complexities that might cause you to change this, but if/when those do arise that's when you modularize).
Structure your directories by feature (Angular conventions do condone BDD, after all):
|-app/
|-|-cart/
|-|-|-CartItemsModel.js
|-|-|-OrderRepository.js
|-|-|-cart.html
|-|-|-add-item-modal/
|-##some more cart stuff
|-|-checkout/
|-|-|-confirmation/
|-|-|-|-confirmation.html
|-|-|-|-confirmation.less
If you're writing feature files or getting acceptance criteria from your employer, you can even model your directory structure directly after those features or requirement sets. That makes everything smooth from defining the scope of an iteration through documentation through revisiting code at a later time.
Both example work. But for instance with the example 2, this syntax can be used for separation of concern. You may need a module that is responsible for providing services which gives you function for Rest calls. Or another module that package some directives.
It's generally considered good practice to segregate your modules into different files. This will ensure that you are practicing good code control, and gives your code a greater degree of portability and debug-ability. Instead of declaring modules in the same file, declare them in different files with their module name.
It's good practice to segregate your files based on their module-controller relationship -- that is, each controller should have its own file, like this:
\scripts\controllers\
- - main.js
- - comments.js
Then, inside your main.js file, you'll start off with the controller declaration:
//main.js
angular.module('app')
.controller('MainController', function ($scope, $http) {
// Controller-scope stuff here
});
Finally, inside your comments.js file:
angular.module('app')
.controller('CommentsController', function($scope, $http, $routeParams) {
// Comment controller code
});
One way to help with organization right off the bat is to organize your files is with a seed template, like Angular Seed.
Just remember that you want to keep your module('app').controller('whatever') inside whatever.js, and any other .factory('forWhatever') (like in your example) should be contained with that parent .controller('whatever') inside the whatever.js file.

Resources