Skip to content

Commit e269c14

Browse files
authored
fix($controller): remove instantiating controllers defined on window
This also removes the likewise deprecated `$controllerProvider.allowGlobals()` method. Closes angular#15349 Closes angular#15762 BREAKING CHANGE: The option to instantiate controllers from constructors on the global `window` object has been removed. Likewise, the deprecated `$controllerProvider.allowGlobals()` method that could enable this behavior, has been removed. This behavior had been deprecated since AngularJS v1.3.0, because polluting the global scope is bad. To migrate, remove the call to $controllerProvider.allowGlobals() in the config, and register your controller via the Module API or the $controllerProvider, e.g. ``` angular.module('myModule', []).controller('myController', function() {...}); angular.module('myModule', []).config(function($controllerProvider) { $controllerProvider.register('myController', function() {...}); }); ```
1 parent 19bc521 commit e269c14

File tree

5 files changed

+11
-67
lines changed

5 files changed

+11
-67
lines changed

docs/content/tutorial/step_02.ngdoc

+9-25
Original file line numberDiff line numberDiff line change
@@ -150,38 +150,22 @@ To learn more about AngularJS scopes, see the {@link ng.$rootScope.Scope Angular
150150

151151
# Testing
152152

153-
The "AngularJS way" of separating controller from the view, makes it easy to test code as it is being
154-
developed. If our controller were available on the global namespace, we could simply instantiate it
155-
with a mock scope object:
153+
## Testing Controllers
156154

157-
<br />
158-
```js
159-
describe('PhoneListController', function() {
155+
The "AngularJS way" of separating the controller from the view makes it easy to test code as it is being
156+
developed. In the section "Model and Controller" we have registered our controller via a constructor
157+
function on the `phonecatApp` module.
160158

161-
it('should create a `phones` model with 3 phones', function() {
162-
var scope = {};
163-
var ctrl = new PhoneListController(scope);
164-
165-
expect(scope.phones.length).toBe(3);
166-
});
159+
In tests, we use an AngularJS service, `$controller`, which will retrieve a controller by name. It
160+
also takes a second argument - a map of dependencies that should be injected.
167161

168-
});
169-
```
162+
The following test instantiates `PhoneListController` with a mock scope object,
163+
and verifies that the phones array property on the scope contains three records.
170164

171-
The test instantiates `PhoneListController` and verifies that the phones array property on the
172-
scope contains three records. This example demonstrates how easy it is to create a unit test for
165+
This example demonstrates how easy it is to create a unit test for
173166
code in AngularJS. Since testing is such a critical part of software development, we make it easy to
174167
create tests in AngularJS so that developers are encouraged to write them.
175168

176-
177-
## Testing non-global Controllers
178-
179-
In practice, you will not want to have your controller functions in the global namespace. Instead,
180-
you can see that we have registered it via a constructor function on the `phonecatApp` module.
181-
182-
In this case AngularJS provides a service, `$controller`, which will retrieve your controller by name.
183-
Here is the same test using `$controller`:
184-
185169
<br />
186170
**`app/app.spec.js`:**
187171

src/ng/controller.js

+2-21
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ function identifierForController(controller, ident) {
2626
* {@link ng.$controllerProvider#register register} method.
2727
*/
2828
function $ControllerProvider() {
29-
var controllers = {},
30-
globals = false;
29+
var controllers = {};
3130

3231
/**
3332
* @ngdoc method
@@ -55,21 +54,6 @@ function $ControllerProvider() {
5554
}
5655
};
5756

58-
/**
59-
* @ngdoc method
60-
* @name $controllerProvider#allowGlobals
61-
* @description If called, allows `$controller` to find controller constructors on `window`
62-
*
63-
* @deprecated
64-
* sinceVersion="v1.3.0"
65-
* removeVersion="v1.7.0"
66-
* This method of finding controllers has been deprecated.
67-
*/
68-
this.allowGlobals = function() {
69-
globals = true;
70-
};
71-
72-
7357
this.$get = ['$injector', '$window', function($injector, $window) {
7458

7559
/**
@@ -83,8 +67,6 @@ function $ControllerProvider() {
8367
*
8468
* * check if a controller with given name is registered via `$controllerProvider`
8569
* * check if evaluating the string on the current scope returns a constructor
86-
* * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
87-
* `window` object (deprecated, not recommended)
8870
*
8971
* The string can use the `controller as property` syntax, where the controller instance is published
9072
* as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
@@ -124,8 +106,7 @@ function $ControllerProvider() {
124106
identifier = identifier || match[3];
125107
expression = controllers.hasOwnProperty(constructor)
126108
? controllers[constructor]
127-
: getter(locals.$scope, constructor, true) ||
128-
(globals ? getter($window, constructor, true) : undefined);
109+
: getter(locals.$scope, constructor, true);
129110

130111
if (!expression) {
131112
throw $controllerMinErr('ctrlreg',

src/ng/directive/ngController.js

-4
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@
3131
* The controller instance can be published into a scope property by specifying
3232
* `ng-controller="as propertyName"`.
3333
*
34-
* If the current `$controllerProvider` is configured to use globals (via
35-
* {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
36-
* also be the name of a globally accessible constructor function (deprecated, not recommended).
37-
*
3834
* @example
3935
* Here is a simple form for editing user contact information. Adding, removing, clearing, and
4036
* greeting are methods declared on the controller (see source tab). These methods can

src/ngMock/angular-mocks.js

-2
Original file line numberDiff line numberDiff line change
@@ -2256,8 +2256,6 @@ angular.mock.$RootElementProvider = function() {
22562256
*
22572257
* * check if a controller with given name is registered via `$controllerProvider`
22582258
* * check if evaluating the string on the current scope returns a constructor
2259-
* * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
2260-
* `window` object (deprecated, not recommended)
22612259
*
22622260
* The string can use the `controller as property` syntax, where the controller instance is published
22632261
* as the specified property on the `scope`; the `scope` must be injected into `locals` param for this

test/ng/controllerSpec.js

-15
Original file line numberDiff line numberDiff line change
@@ -95,21 +95,6 @@ describe('$controller', function() {
9595
});
9696

9797

98-
it('should instantiate a controller defined on window if allowGlobals is set',
99-
inject(function($window) {
100-
var scope = {};
101-
var Foo = function() {};
102-
103-
$controllerProvider.allowGlobals();
104-
105-
$window.a = {Foo: Foo};
106-
107-
var foo = $controller('a.Foo', {$scope: scope});
108-
expect(foo).toBeDefined();
109-
expect(foo instanceof Foo).toBe(true);
110-
}));
111-
112-
11398
it('should throw ctrlfmt if name contains spaces', function() {
11499
expect(function() {
115100
$controller('ctrl doom');

0 commit comments

Comments
 (0)