Controllers polluting the Global Namespace

5,161 views
Skip to first unread message

DesHartman

unread,
Aug 30, 2012, 8:30:49 AM8/30/12
to ang...@googlegroups.com
From your examples, you always have controllers created in the global name space like so:

app/js/controllers.js:
function PhoneListCtrl($scope, $http) {
$http.get('phones/phones.json').success(function(data) {
$scope.phones = data;
});
 
$scope.orderProp = 'age';
}

From my limited experience with AngulaJS and JavaScript I believe this is a really bad practise?

I saw an article (not-polluting-global-with-angularjs) referencing the controller function of module as a way to avoid it

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

 So my question is, what is the best practise here? Seems namespace pollution is a bad idea, yet all the examples do it.

Thanks
Des

Pawel Kozlowski

unread,
Aug 30, 2012, 8:53:22 AM8/30/12
to ang...@googlegroups.com
Hi!

Globals are bad, very bad.
The best practice is to declare those controllers on a module level.
This is absolute must for bigger apps.

On Thu, Aug 30, 2012 at 2:30 PM, DesHartman <d...@wiredlizard.com> wrote:

> So my question is, what is the best practise here? Seems namespace
> pollution is a bad idea, yet all the examples do it.

So all those examples are bad :-) Jokes apart - having ability to
declare controllers as global (without a need for a module) is
convenient for short examples. And since you see many short examples
(jsFiddle / plunk) it looks like people are mostly using globals.

But once again - in real-life apps stick to controllers defined on a
module level.

Hope this helps,
Pawel

Des Hartman

unread,
Aug 30, 2012, 5:22:17 PM8/30/12
to ang...@googlegroups.com
Is it possible to change the examples to reflect this policy? As a novice Angular, this has already set a bad precedent in my understanding of Angular.

Would there be any examples around of how to deal with it when there are a lot of controllers? I have a mobile app where I have a controller per view. I would like to declare these controllers in their own file and load them using the ngRouting module. Examples seem to follow global controllers all in one module

Thanks
Des
> --
> You received this message because you are subscribed to the Google Groups "AngularJS" group.
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to angular+u...@googlegroups.com.
> Visit this group at http://groups.google.com/group/angular?hl=en.
>
>

d...@wiredlizard.com

unread,
Sep 2, 2012, 11:10:25 PM9/2/12
to ang...@googlegroups.com, d...@wiredlizard.com
Maybe I should rephrase my question:

Why are Controllers not put in Modules the same way Filters and Directives are in the examples?


Thanks
Des

Michael Alan Dorman

unread,
Sep 4, 2012, 10:34:12 AM9/4/12
to ang...@googlegroups.com, d...@wiredlizard.com
d...@wiredlizard.com writes:
> Why are Controllers not put in Modules the same way Filters and
> Directives are in the examples?

I can't speak for the tutorial writers, but I would *guess* that it was
simply to remove another layer of stuff they would have to explain in
the tutorial.

That said, I almost passed on Angular because polluting the global
namespace was the only way that was presented and that struck me as
amateurish. Fortunately, I happened to look at the angular.module docs
and realized that it was not obligatory.

Mike.

Peter Bacon Darwin

unread,
Sep 4, 2012, 12:01:06 PM9/4/12
to ang...@googlegroups.com

I would vote for this to change in the tutorial as it doesn't fit well with the high quality engineered approach that angular promotes

Pete
...from my mobile.

Godmar Back

unread,
Sep 4, 2012, 2:04:33 PM9/4/12
to ang...@googlegroups.com

So I tried to look up what Angular modules are about.

The documentation at http://docs.angularjs.org/guide/module talks about the 'advantages' of modules without talking about what modules are.

The "The Basics" example at that site links to a broken fiddle: http://jsfiddle.net/9uYnc/

So, perhaps the documentation should be fixed before introducing controllers in conjunction with modules.

 - Godmar

Cary Landholt

unread,
Sep 5, 2012, 3:14:57 AM9/5/12
to ang...@googlegroups.com
Fixed the fiddle.  http://jsfiddle.net/9uYnc/2/

DesHartman

unread,
Sep 5, 2012, 5:24:15 AM9/5/12
to ang...@googlegroups.com
Mike,

I considered the fact that the writers of the examples put the controllers in global space for simplicity and not to overload newcomers with too much information. However the practise is widespread throughout all the examples, so this is why I was concerned.

If you follow the tutorial, you see that they build on concepts to introduce better ways of doing things. Sadly, they never introduce controllers in modules and I think that is a mistake.

If filters and directives have to be put in modules, why not controllers. I think it will be way more consistent if all of them are modules from the word go.


Des

Witold Szczerba

unread,
Sep 5, 2012, 5:43:28 AM9/5/12
to ang...@googlegroups.com
Can someone explain me what is so wrong with controllers constructor
functions in global name space?
Everyone repeats the same: polluting global name space is wrong, bla
bla, but what does exactly the term "polluting" mean to you? Come on
people, it was always about making variables/functions like "a", "b",
"idx" or "result", "checkUser" or anything which is LOCAL to some
scope, but controllers are not supposed to be local, they actually
define your application and either way you are going to put them all
in ONE BAG of all available controllers, aren't you?

How many: UserAccountController controllers are you going to scatter
in all your modules? Even if you need two distinct in two different
modules, the application consisting of both modules is not going to
work anyway, because the module name is not part of controller name,
is it?

I must have missed something, so again, what is wrong with global
controller constructor functions in an application which needs
reference those controllers everywhere anyway?

Regards,
Witold Szczerba

Michael Alan Dorman

unread,
Sep 5, 2012, 6:14:27 AM9/5/12
to ang...@googlegroups.com
Witold Szczerba <pljos...@gmail.com> writes:
> I must have missed something, so again, what is wrong with global
> controller constructor functions in an application which needs
> reference those controllers everywhere anyway?

It is generally recognized as a best practice for Javascript to put as
little stuff in the global namespace as possible, since, historically,
many libraries were promiscuous about it, and it led to unfortunate,
hard to debug conflicts.

You may, of course, argue that the chance of this happening is very low,
and you would probably be right, especially given the tediously long
names that people tend to give to their controllers in angular.

But let me turn it around: why, given that there is another alternative
that eliminates the need, would you choose to dump stuff in the global
namespace?

Mike.

Peter Bacon Darwin

unread,
Sep 5, 2012, 6:14:48 AM9/5/12
to ang...@googlegroups.com

Is this a serious question?
One nice thing about modules is that they are pluggable so even if the file containing the module is loaded you can choose not to use it by not depending upon it. In the same vein you can setup dependencies between modules containing controllers which you can't do between global objects.
Pete
...from my mobile.

Cary Landholt

unread,
Sep 5, 2012, 9:10:35 AM9/5/12
to ang...@googlegroups.com
I agree with Des.  It's nice to demonstrate the simplicity of Angular by jotting down a few functions and getting it to "just work"; however, it has the side effect of being a bit confusing once you begin needing more from Angular.  Somehow controllers are treated differently.

Compared to other libraries like backbone and ember, Angular's price of entry is pretty minimal, even if you throw in modules.

The following is fairly lean.

var myApp = angular.module('myApp', []);
var myController = myApp.controller('myController', ['$scope', function ($scope) { /* controller code here */}]);
var myDirective = myApp.directive('myDirective', [function () { /* directive code here */}]);
var myFilter = myApp.filter('myFilter', [function (params) { /* filter code here */}]);


Thanks,
Cary

Godmar Back

unread,
Sep 5, 2012, 9:29:04 AM9/5/12
to ang...@googlegroups.com

Thank you, I had fixed it, too at http://jsfiddle.net/9uYnc/1/ 

It's still broken on the documentation site - do you have access to that?

I think the larger point is that many of the examples in the documentation do not work, which can make for a frustrating learning experience (or, depending on how you look at it, an involved experience if you have to fix the example!)

Witold Szczerba

unread,
Sep 5, 2012, 9:37:00 AM9/5/12
to ang...@googlegroups.com
On 5 September 2012 15:29, Godmar Back <god...@gmail.com> wrote:
> It's still broken on the documentation site - do you have access to that?
>
> I think the larger point is that many of the examples in the documentation
> do not work, which can make for a frustrating learning experience (or,
> depending on how you look at it, an involved experience if you have to fix
> the example!)

Hi,
all the AngularJS project, including web page is at github, so
everyone can fork, fix and issue a pull request.

Regards,
Witold Szczerba

Godmar Back

unread,
Sep 5, 2012, 10:37:01 AM9/5/12
to ang...@googlegroups.com
Ok - fair enough. I gave this a try, just to ascertain how big the contribution hurdle is: https://github.com/angular/angular.js/pull/1336

My experience - building the documentation locally worked more or less ok. It doesn't run well locally, though, because they have hardwired links to docs.angularjs.org in their HTML: https://github.com/angular/angular.js/blob/master/docs/src/templates/index.html#L141 

 - Godmar

Michael Alan Dorman

unread,
Sep 5, 2012, 10:56:41 AM9/5/12
to ang...@googlegroups.com
Cary Landholt <ca...@landholt.com> writes:
> The following is fairly lean.
>
> var myApp = angular.module('myApp', []);
> var myController = myApp.controller('myController', ['$scope',
> function ($scope) { /* controller code here */}]);
> var myDirective = myApp.directive('myDirective', [function () { /*
> directive code here */}]);
> var myFilter = myApp.filter('myFilter', [function (params) { /*
> filter code here */}]);

I, personally, do away with the vars as well and just chain it all
together. ;)

Don't get me wrong, I agree that beyond, say, an introductory
screencast, it would be better if this way of doing things was shown as
"the standard". No need to encourage bad habits---or, as was nearly my
case, make people think that the bad habits are mandatory, and thus turn
them off the framework.

Mike.

Cary Landholt

unread,
Sep 5, 2012, 11:17:55 AM9/5/12
to ang...@googlegroups.com
I too chain my vars, but chose not to in the post for clarity.  :)

DesHartman

unread,
Sep 6, 2012, 8:30:46 AM9/6/12
to ang...@googlegroups.com
I had a quick look at the Angular seed and the global controllers is even there. It actually shows how bad this is, because all the other parts are all modules, but the controllers are global. The confusion comes in when you look at the app.js decalration:

// Declare app level module which depends on filters, and services
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives']).

No controllers here!!

What you should see:

// Declare app level module which depends on filters, directive, controllers  and services
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers']).


and the actual controller.js file 

'use strict';

/* Controllers */

angular.module('myApp.controllers', []).
    controller('MyCtrl1',function MyCtrl1() {
    }).
    controller('MyCtrl2', function MyCtrl2() {
    });


Only part I was not sure of is where to put the inject statements?


MyCtrl1.$inject = [];
MyCtrl2.$inject = [];
 


Vote for the seed to be altered. I have never done a pull request so not sure what is involved.

Des


Michael Alan Dorman

unread,
Sep 6, 2012, 9:39:05 AM9/6/12
to ang...@googlegroups.com
DesHartman <d...@wiredlizard.com> writes:
> angular.module('myApp.controllers', []).
>
> controller('MyCtrl1',function MyCtrl1() {
>
> }).
>
> controller('MyCtrl2', function MyCtrl2() {
>
> });
>
> Only part I was not sure of is where to put the inject statements?

All of the different parts allow passing an arrayref as the content,
declaring the dependencies first. So the above becomes:

angular.module('myApp.controllers', []).
controller('MyCtrl1', ['dep1', 'dep2', function MyCtrl1() {
}]).
controller('MyCtrl2', ['dep3', 'dep4', function MyCtrl2() {
}]);

> Vote for the seed to be altered. I have never done a pull request so
> not sure what is involved.

Fork it on github, clone the fork locally, make a topic branch, make the
changes, push them back to github, make sure the topic branch is
selected, hit the 'pull request' button, fill in the info.

Mike.

Jennifer K Baxter

unread,
Sep 6, 2012, 10:04:09 AM9/6/12
to ang...@googlegroups.com
Mike,

Using your method makes the routeProvider in app.js in the angular-seed not able to find the controller. How would you reference the controller in this case?

angular.module('myApp', ['myApp.controllers','myApp.filters', 'myApp.services', 'myApp.directives','ui.directives']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/view1', {templateUrl: 'partials/profile.html', controller: MyCntrl1});

Results in "Uncaught ReferenceError: MyCntrl1 is not defined from myApp" 

Remo Koch

unread,
Sep 6, 2012, 10:05:38 AM9/6/12
to ang...@googlegroups.com
Jennifer,

Try to wrap it in quotes:
angular.module('myApp', ['myApp.controllers','myApp.filters', 'myApp.services', 'myApp.directives','ui.directives']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/view1', {templateUrl: 'partials/profile.html', controller: 'MyCntrl1'});

Cheers Remo

2012/9/6 Jennifer K Baxter <jennifer...@gmail.com>

--

Peter Bacon Darwin

unread,
Sep 6, 2012, 10:05:22 AM9/6/12
to ang...@googlegroups.com
as a string :

$routeProvider.when('/view1', {templateUrl: 'partials/profile.html', controller: 'MyCntrl1'});


--

Jennifer K Baxter

unread,
Sep 6, 2012, 10:07:18 AM9/6/12
to ang...@googlegroups.com
Fantastic, fixed. This is a much better way to work, I'm glad this discussion came up.

Getulio Romão Campos Junior

unread,
Sep 6, 2012, 2:48:37 PM9/6/12
to ang...@googlegroups.com
DesHatman,

My suggesttion would be:

controller('MyCtrl1',function MyCtrl1() {
    }).$inject = [];




DesHartman

unread,
Sep 6, 2012, 5:42:04 PM9/6/12
to ang...@googlegroups.com
Jennifer

Sorry I missed that you need to quote the controllers now.  


Des

DesHartman

unread,
Sep 6, 2012, 5:45:03 PM9/6/12
to ang...@googlegroups.com
In this example the controllers have the same amount of params, ie.e, none, but if each controller had different params?

From the tutorial this is needed when minifying the code, so I would think this is specific to EACH controller

Any ideas?

Thanks
Des

DesHartman

unread,
Sep 6, 2012, 5:45:49 PM9/6/12
to ang...@googlegroups.com
Thanks Mike, I'll give it a go

Des

aaron

unread,
Oct 4, 2012, 11:12:02 AM10/4/12
to ang...@googlegroups.com
If you use a string for the controller name, how do you use the "resolve" object in the $routeProvider without having to put the entire resolve object into the $routeProvider config?

alm...@gmail.com

unread,
Nov 11, 2012, 5:34:55 AM11/11/12
to ang...@googlegroups.com
Hi, 
Was looking at this and it makes senes I also don't like the idea of polluting the global namespace but if that's the case how would or what is the best practices for having a controller per view. I don't think having a module with 5 or 6 controllers makes sense, to much code in one file. 

Almog


On Thursday, August 30, 2012 3:30:49 PM UTC+3, DesHartman wrote:
From your examples, you always have controllers created in the global name space like so:

app/js/controllers.js:
function PhoneListCtrl($scope, $http) {
$http.get('phones/phones.json').success(function(data) {
$scope.phones = data;
});
 
$scope.orderProp = 'age';
}

From my limited experience with AngulaJS and JavaScript I believe this is a really bad practise?

I saw an article (not-polluting-global-with-angularjs) referencing the controller function of module as a way to avoid it

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

 So my question is, what is the best practise here? Seems namespace pollution is a bad idea, yet all the examples do it.

Thanks
Des

Vadim Vdovin

unread,
Nov 11, 2012, 5:50:34 AM11/11/12
to ang...@googlegroups.com, alm...@gmail.com

Just put a link of your module into a global var:

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

And whenever you want create a controller:

myApp.controller("MyCtrl", ["$http", function($http) {

}]);

alm...@gmail.com

unread,
Nov 11, 2012, 10:00:06 AM11/11/12
to ang...@googlegroups.com, alm...@gmail.com
Thanks I did that without evening knowing. 

Pascal Precht

unread,
Nov 26, 2012, 4:42:57 AM11/26/12
to ang...@googlegroups.com, alm...@gmail.com
Anybody tested this?

When I try to define my controller under an angular namespace using

angular.module('myApp.controllers', []).controller('MyCtrl', function (dep1, dep2) {

}).$inject = [dep1, dep2];


I got an "'MyCtrl' is not a function, got undefined" error....

Pawel Kozlowski

unread,
Nov 26, 2012, 5:03:50 AM11/26/12
to ang...@googlegroups.com
Hi!

You should use different style of injecting dependencies with
controllers declared on the module level:

angular.module('myApp.controllers', []).controller('MyCtrl', ['dep1',
'dep2', function (dep1, dep2) {
}]);

More info here: http://docs.angularjs.org/guide/di ("Dependency
Annotation" section).

Hope this helps,
Pawel


On Mon, Nov 26, 2012 at 10:42 AM, Pascal Precht <pascal...@gmail.com> wrote:
> angular.module('myApp.controllers', []).controller('MyCtrl', function (dep1,
> dep2) {
>
> }).$inject = [dep1, dep2];



--
Question? Send a fiddle
(http://jsfiddle.net/pkozlowski_opensource/Q2NpJ/) or a plunk
(http://plnkr.co/)
Need help with jsFiddle? Check this:
http://pkozlowskios.wordpress.com/2012/08/12/using-jsfiddle-with-angularjs/

Looking for UI widget library for AngularJS? Here you go:
http://angular-ui.github.com/

Pascal Precht

unread,
Nov 26, 2012, 5:20:30 AM11/26/12
to ang...@googlegroups.com
Thanks for the fast answer.

But this doesn't solve anything. Declaring dependencies in array notation was the first try I did. :)

Pawel Kozlowski

unread,
Nov 26, 2012, 5:24:23 AM11/26/12
to ang...@googlegroups.com
Hey!

Sorry Pascal, might have missed something... I know that this syntax
is good, we are using it all the time, have a look at our sample app:
https://github.com/angular-app/angular-app/blob/master/client/src/app/admin/projects/admin-projects.js#L30

What is the thing you are struggling with?

Cheers,
Pawel
> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to
> angular+u...@googlegroups.com.
> Visit this group at http://groups.google.com/group/angular?hl=en-US.

Witold Szczerba

unread,
Nov 26, 2012, 5:26:56 AM11/26/12
to ang...@googlegroups.com, alm...@gmail.com

Look closely to where you get that exception from. You have removed MyCtrl from the global name space and you are still trying to reference it somewhere as it was still global. Replace that reference with a string 'MyCtrl' and you will be fine. I bet this is in $route configuration.

Regards,
Witold Szczerba
---
Sent from my mobile phone.

--

Pascal Precht

unread,
Nov 26, 2012, 6:08:34 AM11/26/12
to ang...@googlegroups.com, alm...@gmail.com
Negative.

Of course I updated the $route configuration and referenced the controllers as string.

Pascal Precht

unread,
Nov 26, 2012, 6:11:10 AM11/26/12
to ang...@googlegroups.com
Will have a look, thanks a lot bro!

Andy Joslin

unread,
Nov 26, 2012, 8:00:05 AM11/26/12
to ang...@googlegroups.com
If you're on unix, cd to your project and do 'ack MyCtrl' to find everywhere it's mentioned.  It still sounds like you're referencing it somewhere.

Pascal Precht

unread,
Nov 26, 2012, 9:58:58 AM11/26/12
to ang...@googlegroups.com
Argh. Got it now.

'MyCtrl' !== 'MyCtrl1'

Sorry guys.

Armin Keyvanloo

unread,
Feb 5, 2013, 12:20:27 AM2/5/13
to ang...@googlegroups.com
Apologies in advance if the answer to this is totally obvious, but having defined the controller like:

myApp.controller('MyCtrl1', ['$window', function ($window) {
.....
}]);

How do I get a handle to this controller for unit testing?
  beforeEach(function(){
    myCtrl1 = new MyCtrl1(); <----- current auto generated test skeleton (error: unresolved type MyCtrl1)
  });

Witold Szczerba

unread,
Feb 5, 2013, 3:04:12 AM2/5/13
to ang...@googlegroups.com

Have you registered the module of that controller in your test?

Regards,
Witold Szczerba
---
Sent from my mobile phone.

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Pawel Kozlowski

unread,
Feb 5, 2013, 3:23:42 AM2/5/13
to ang...@googlegroups.com
Hi!

You need to use the $controller service to instantiate your
controllers. There was a thread about it just few days back:
https://groups.google.com/group/angular/browse_thread/thread/69f528516277b95c

The code would look sth like:

myCtrl1 = $controller('MyCtrl1', {
$scope: {} <-your fake scope here
});
> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to angular+u...@googlegroups.com.
>
> To post to this group, send email to ang...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>



--
Looking for bootstrap-based widget library for AngularJS?
http://angular-ui.github.com/bootstrap/

Joe Hanink

unread,
Apr 18, 2013, 3:18:58 AM4/18/13
to ang...@googlegroups.com
after registering my controllers with the module

myApp.controller('MyCtrl', function($scope) { ... });

this stopped working for me:

<div ng-controller="MyCtrl"></div>

I don't want to have to use the other form:

<div class="ng-controller: 'MyCtrl' "></div>

Recommendations?

Lutz Epperlein

unread,
Apr 18, 2013, 3:26:33 AM4/18/13
to ang...@googlegroups.com
Try this:

myApp.controller('MyCtrl', [ '$scope', function($scope) { ... } ] );

You have to inject the services you need in your controller.

HTH

code solver

unread,
Jul 24, 2013, 6:58:38 AM7/24/13
to ang...@googlegroups.com


If you are getting that error you have to write your controller name within the quotes.

Reply all
Reply to author
Forward
0 new messages