1

I've seen this post AngularJS best practices for module declaration? But I am still a little confused about the best way to declare and separate angularJS files for modules, controllers, services etc.

I understand it is good practice to wrap controllers and services in IIFEs because it prevents them from being used out of scope. And it is good practice to separate your controllers and modules into separate files for organization.

My question is, if I have a controller file

myCtrl.js

(function(){
  "use strict";

  app.controller("myCtrl", ['$scope', function($scope) {
    $scope.firstName = "John";
    $scope.lastName = "Doe";
  }]);
})();

A directive file

myDirective.js

(function(){
  "use strict";
  app.directive("w3TestDirective", function() {
    return {
      template : "I was made in a directive constructor!"
    };
  });
})();

What would be the best practice for declaring the module in its own file

myModule.js

Should it be left at global scope so anything can access it as follows:

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

Or is there a way to wrap this in something like an IIFE to keep it from global scope and yet still be accessible to the other files?

Community
  • 1
  • 1

2 Answers2

0

In controller and directive snippets IIFEs aren't needed because nothing is exposed to global scope.

var app = ... shouldn't be exposed to global scope. Module getter can be used instead:

var app = angular.module("myApp")

This requires to preserve the order of loaded JS files. The module should be defined first with angular.module("myApp", []), only then then module units can be defined.

Unless the app uses JS modules (AMD, CommonJS, ES6) for modularity, it is beneficial to follow 'one module per file' pattern. This allows to considerably improve testability and never run into module-related race conditions:

(function(){
  "use strict";

  var app = angular.module("myApp.myCtrl", []);

  app.controller("myCtrl", ['$scope', function($scope) {
    $scope.firstName = "John";
    $scope.lastName = "Doe";
  }]);
})();

angular.module("myApp", ["myApp.myCtrl", "myApp.w3TestDirective"]);

In this case it doesn't matter in which order module files are loaded.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • So one file has the module `angular.module("myApp", ["myApp.myCtrl", "myApp.w3TestDirective"]);` and one has either the controller or directive wrapped in an IIFE life you showed with the module being assigned to `var app` like you showed? I guess I still don't get why the module definition isn't exposed globablly if done that way. –  Dec 26 '16 at 18:44
  • Because it doesn't have `var app = angular.module(...)`. If you don't have `var ...` or `function ...` in the scope of JS file, nothing is exposed to global scope. Angular was designed in a way that allows to write the app without exposing anything to global scope, however, for readability and some OOP concerns it may be beneficial to have local variables and functions wrapped in IIFEs. – Estus Flask Dec 26 '16 at 19:23
0

we can build relation between angular files for example

  1. controllers
  2. services
  3. factories
  4. and so on

with angular module

for example: angular.module("myApp",["dependencies"])

angular.module("myApp").controller("myCtrl",function(){}) or angular.module("myApp").service("myservice",function(){})

pejman
  • 740
  • 7
  • 13