Not polluting global with angularjs

In angularjs, we define our controllers into window. While this would not create name clashes with other js modules and plugins, it is still not a good practise: a single application should expose a single object to the global namespace.

This is the usual way, defined in window:

function UserController($scope) { ... }

HTML:

<div ng-controller="UserController">

This is what I think of:

myApp.UserController = function ($scope) { ... };

So in that case, I should be initiating controller from html like this

<div ng-controller="myApp.UserController">

What do you think?

One of the ways around it is to define it within Angular itself such as the way you described. In other words:

angular.module('YourApp').controller('ControllerName', function($scope) {})

I have confirmed the above method doesn't pollute the global namespace.

Edit: You also don't need to use <div ng-controller="myApp.UserController"> as you could define myApp in the attribute ng-app: <body ng-app="myApp"> That way you could call the ng-controller without prefixing myApp every time.

The cleanest way of defining controllers is 1 per file. Each file should be wrapped with an immediately invoked function expression (IIFE) or closure that allows it to have its own local variables without polluting the global scope. This is the approach I take on my projects:

my-app.js - Primary Module Definition File - This file's main purpose is to define an application module and its dependencies, define routing (if routing is being used), and configure providers. In its simplest form it looks like this:

(function (angular) {
  angular.module('myApp', ['myApp.someFeature']);
}(angular));

some-feature/some-feature.js - feature module definition file - This file defines a module for a feature and any dependencies that this feature requires. This can be any logical grouping, not just a feature. This makes it very easy to bring the feature into another module or application if necessary.

(function (angular) {
  angular.module('myApp.someFeature', []);
}(angular));

some-feature/some-feature-controller.js - controller required for the feature - If the feature included multiple controllers, a more descriptive name would be needed, but lets assume this feature only needs 1 controller.

(function (angular) {
  function SomeFeatureController($scope) {
    ...
  }

  angular
    .module('myApp.someFeature')
    .controller('SomeFeatureController', SomeFeatureController);
}(angular));

index.html - Page html file - Pretty self explanatory

<html ng-app="myApp">
  <head>
    <title>My Angular App</title>
    <!-- Note: Angular and jQuery (if used) go in head so they delay view loading -->
    <script type="text/javascript" language="javascript" src="angular.js"></script>
  </head>
  <body ng-controller="SomeFeatureController">
    Content here....
    <!-- Note application files go at the end of the body so they do not delay view loading -->
    <script type="text/javascript language="javascript src="my-app.js">
    <script type="text/javascript language="javascript src="some-feature/some-feature.js">
    <script type="text/javascript language="javascript src="some-feature/some-feature-controller.js">
  </body>
</html>

As suggested by btesser writing controllers in separate files and functions and defining its methods in the controller's function prototype is a best practice for AngularJS apps. You can use a closure or IIFE to prevent polluting the global namespace, it will expose your functions only to the current context.

(function(){
'use strict';

angular.module('myApp', [])
.controller('MyAppCtrl', MyAppCtrl)

;
  
function MyAppCtrl(){
  this.greeting = 'I\'m app ctrl';
}
  
MyAppCtrl.prototype.hello = function(){
  alert(this.greeting);
}

})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyAppCtrl as ctrl">
  <pre>{{ctrl | json}}</pre>
  <button ng-click="ctrl.hello()">Hello!</button>
</div>
  

 
</body>