fix($controller): remove instantiating controllers defined on window
This also removes the likewise deprecated `$controllerProvider.allowGlobals()` method. Closes #15349 Closes #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() {...}); }); ```
This commit is contained in:
@@ -150,38 +150,22 @@ To learn more about AngularJS scopes, see the {@link ng.$rootScope.Scope Angular
|
||||
|
||||
# Testing
|
||||
|
||||
The "AngularJS way" of separating controller from the view, makes it easy to test code as it is being
|
||||
developed. If our controller were available on the global namespace, we could simply instantiate it
|
||||
with a mock scope object:
|
||||
## Testing Controllers
|
||||
|
||||
<br />
|
||||
```js
|
||||
describe('PhoneListController', function() {
|
||||
The "AngularJS way" of separating the controller from the view makes it easy to test code as it is being
|
||||
developed. In the section "Model and Controller" we have registered our controller via a constructor
|
||||
function on the `phonecatApp` module.
|
||||
|
||||
it('should create a `phones` model with 3 phones', function() {
|
||||
var scope = {};
|
||||
var ctrl = new PhoneListController(scope);
|
||||
In tests, we use an AngularJS service, `$controller`, which will retrieve a controller by name. It
|
||||
also takes a second argument - a map of dependencies that should be injected.
|
||||
|
||||
expect(scope.phones.length).toBe(3);
|
||||
});
|
||||
The following test instantiates `PhoneListController` with a mock scope object,
|
||||
and verifies that the phones array property on the scope contains three records.
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
The test instantiates `PhoneListController` and verifies that the phones array property on the
|
||||
scope contains three records. This example demonstrates how easy it is to create a unit test for
|
||||
This example demonstrates how easy it is to create a unit test for
|
||||
code in AngularJS. Since testing is such a critical part of software development, we make it easy to
|
||||
create tests in AngularJS so that developers are encouraged to write them.
|
||||
|
||||
|
||||
## Testing non-global Controllers
|
||||
|
||||
In practice, you will not want to have your controller functions in the global namespace. Instead,
|
||||
you can see that we have registered it via a constructor function on the `phonecatApp` module.
|
||||
|
||||
In this case AngularJS provides a service, `$controller`, which will retrieve your controller by name.
|
||||
Here is the same test using `$controller`:
|
||||
|
||||
<br />
|
||||
**`app/app.spec.js`:**
|
||||
|
||||
|
||||
+2
-21
@@ -26,8 +26,7 @@ function identifierForController(controller, ident) {
|
||||
* {@link ng.$controllerProvider#register register} method.
|
||||
*/
|
||||
function $ControllerProvider() {
|
||||
var controllers = {},
|
||||
globals = false;
|
||||
var controllers = {};
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -55,21 +54,6 @@ function $ControllerProvider() {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $controllerProvider#allowGlobals
|
||||
* @description If called, allows `$controller` to find controller constructors on `window`
|
||||
*
|
||||
* @deprecated
|
||||
* sinceVersion="v1.3.0"
|
||||
* removeVersion="v1.7.0"
|
||||
* This method of finding controllers has been deprecated.
|
||||
*/
|
||||
this.allowGlobals = function() {
|
||||
globals = true;
|
||||
};
|
||||
|
||||
|
||||
this.$get = ['$injector', '$window', function($injector, $window) {
|
||||
|
||||
/**
|
||||
@@ -83,8 +67,6 @@ function $ControllerProvider() {
|
||||
*
|
||||
* * check if a controller with given name is registered via `$controllerProvider`
|
||||
* * check if evaluating the string on the current scope returns a constructor
|
||||
* * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
|
||||
* `window` object (deprecated, not recommended)
|
||||
*
|
||||
* The string can use the `controller as property` syntax, where the controller instance is published
|
||||
* as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
|
||||
@@ -124,8 +106,7 @@ function $ControllerProvider() {
|
||||
identifier = identifier || match[3];
|
||||
expression = controllers.hasOwnProperty(constructor)
|
||||
? controllers[constructor]
|
||||
: getter(locals.$scope, constructor, true) ||
|
||||
(globals ? getter($window, constructor, true) : undefined);
|
||||
: getter(locals.$scope, constructor, true);
|
||||
|
||||
if (!expression) {
|
||||
throw $controllerMinErr('ctrlreg',
|
||||
|
||||
@@ -31,10 +31,6 @@
|
||||
* The controller instance can be published into a scope property by specifying
|
||||
* `ng-controller="as propertyName"`.
|
||||
*
|
||||
* If the current `$controllerProvider` is configured to use globals (via
|
||||
* {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
|
||||
* also be the name of a globally accessible constructor function (deprecated, not recommended).
|
||||
*
|
||||
* @example
|
||||
* Here is a simple form for editing user contact information. Adding, removing, clearing, and
|
||||
* greeting are methods declared on the controller (see source tab). These methods can
|
||||
|
||||
Vendored
-2
@@ -2256,8 +2256,6 @@ angular.mock.$RootElementProvider = function() {
|
||||
*
|
||||
* * check if a controller with given name is registered via `$controllerProvider`
|
||||
* * check if evaluating the string on the current scope returns a constructor
|
||||
* * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
|
||||
* `window` object (deprecated, not recommended)
|
||||
*
|
||||
* The string can use the `controller as property` syntax, where the controller instance is published
|
||||
* as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
|
||||
|
||||
@@ -95,21 +95,6 @@ describe('$controller', function() {
|
||||
});
|
||||
|
||||
|
||||
it('should instantiate a controller defined on window if allowGlobals is set',
|
||||
inject(function($window) {
|
||||
var scope = {};
|
||||
var Foo = function() {};
|
||||
|
||||
$controllerProvider.allowGlobals();
|
||||
|
||||
$window.a = {Foo: Foo};
|
||||
|
||||
var foo = $controller('a.Foo', {$scope: scope});
|
||||
expect(foo).toBeDefined();
|
||||
expect(foo instanceof Foo).toBe(true);
|
||||
}));
|
||||
|
||||
|
||||
it('should throw ctrlfmt if name contains spaces', function() {
|
||||
expect(function() {
|
||||
$controller('ctrl doom');
|
||||
|
||||
Reference in New Issue
Block a user