diff --git a/docs/content/error/$compile/noident.ngdoc b/docs/content/error/$compile/noident.ngdoc deleted file mode 100644 index 9770a94585e1..000000000000 --- a/docs/content/error/$compile/noident.ngdoc +++ /dev/null @@ -1,71 +0,0 @@ -@ngdoc error -@name $compile:noident -@fullName Controller identifier is required. -@description - -When using the `bindToController` feature of AngularJS, a directive is required -to have a Controller identifier, which is initialized in scope with the value of -the controller instance. This can be supplied using the "controllerAs" property -of the directive object, or alternatively by adding " as IDENTIFIER" to the controller -name. - -For example, the following directives are valid: - -```js -// OKAY, because controller is a string with an identifier component. -directive("okay", function() { - return { - bindToController: true, - controller: "myCtrl as $ctrl", - scope: { - text: "@text" - } - }; -}); - - -// OKAY, because the directive uses the controllerAs property to override -// the controller identifier. -directive("okay2", function() { - return { - bindToController: true, - controllerAs: "$ctrl", - controller: function() { - - }, - scope: { - text: "@text" - } - }; -}); -``` - -While the following are invalid: - -```js -// BAD, because the controller property is a string with no identifier. -directive("bad", function() { - return { - bindToController: true, - controller: "noIdentCtrl", - scope: { - text: "@text" - } - }; -}); - - -// BAD because the controller is not a string (therefore has no identifier), -// and there is no controllerAs property. -directive("bad2", function() { - return { - bindToController: true, - controller: function noControllerAs() { - - }, - scope: { - text: "@text" - } - }; -}); -``` diff --git a/src/ng/compile.js b/src/ng/compile.js index 02cd0bdbaa94..d769424c6366 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -360,9 +360,7 @@ * * #### `bindToController` * This property is used to bind scope properties directly to the controller. It can be either - * `true` or an object hash with the same format as the `scope` property. Additionally, a controller - * alias must be set, either by using `controllerAs: 'myAlias'` or by specifying the alias in the controller - * definition: `controller: 'myCtrl as myAlias'`. + * `true` or an object hash with the same format as the `scope` property. * * When an isolate scope is used for a directive (see above), `bindToController: true` will * allow a component to have its properties bound to the controller, rather than to scope. @@ -1027,20 +1025,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { bindings.bindToController = parseIsolateBindings(directive.bindToController, directiveName, true); } - if (isObject(bindings.bindToController)) { - var controller = directive.controller; - var controllerAs = directive.controllerAs; - if (!controller) { - // There is no controller, there may or may not be a controllerAs property - throw $compileMinErr('noctrl', - 'Cannot bind to controller without directive \'{0}\'s controller.', - directiveName); - } else if (!identifierForController(controller, controllerAs)) { - // There is a controller, but no identifier or controllerAs property - throw $compileMinErr('noident', - 'Cannot bind to controller without identifier for directive \'{0}\'.', - directiveName); - } + if (bindings.bindToController && !directive.controller) { + // There is no controller + throw $compileMinErr('noctrl', + 'Cannot bind to controller without directive \'{0}\'s controller.', + directiveName); } return bindings; } @@ -2709,7 +2698,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var bindings = controllerDirective.$$bindings.bindToController; if (preAssignBindingsEnabled) { - if (controller.identifier && bindings) { + if (bindings) { controller.bindingInfo = initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective); } else { @@ -3412,8 +3401,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } - // Set up $watches for isolate scope and controller bindings. This process - // only occurs for isolate scopes and new scopes with controllerAs. + // Set up $watches for isolate scope and controller bindings. function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) { var removeWatchCollection = []; var initialChanges = {}; diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index e4a8ddf4e960..3126a2dad044 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -6126,154 +6126,113 @@ describe('$compile', function() { }); - it('should throw noident when missing controllerAs directive property', function() { - module(function($compileProvider) { - $compileProvider.directive('noIdent', valueFn({ - templateUrl: 'test.html', - scope: { - 'data': '=dirData', - 'oneway': '')($rootScope); - }).toThrowMinErr('$compile', 'noident', - 'Cannot bind to controller without identifier for directive \'noIdent\'.'); - }); - }); - - - it('should throw noident when missing controller identifier', function() { - module(function($compileProvider, $controllerProvider) { - $controllerProvider.register('myCtrl', function() {}); - $compileProvider.directive('noIdent', valueFn({ - templateUrl: 'test.html', - scope: { - 'data': '=dirData', - 'oneway': '')($rootScope); - }).toThrowMinErr('$compile', 'noident', - 'Cannot bind to controller without identifier for directive \'noIdent\'.'); - }); - }); + controllerAs: 'myCtrl' + }], + scopeOptions = [{ + description: 'isolate scope', + scope: {} + }, { + description: 'new scope', + scope: true + }, { + description: 'no scope', + scope: false + }], - it('should bind to controller via object notation (isolate scope)', function() { - var controllerCalled = false; - module(function($compileProvider, $controllerProvider) { - $controllerProvider.register('myCtrl', function() { - this.check = function() { - expect(this.data).toEqualData({ - 'foo': 'bar', - 'baz': 'biz' - }); - expect(this.oneway).toEqualData({ - 'foo': 'bar', - 'baz': 'biz' - }); - expect(this.str).toBe('Hello, world!'); - expect(this.fn()).toBe('called!'); - }; - controllerCalled = true; - if (preAssignBindingsEnabled) { - this.check(); - } else { - this.$onInit = this.check; - } - }); - $compileProvider.directive('fooDir', valueFn({ - templateUrl: 'test.html', - bindToController: { - 'data': '=dirData', - 'oneway': 'isolate

'); - $rootScope.fn = valueFn('called!'); - $rootScope.whom = 'world'; - $rootScope.remoteData = { - 'foo': 'bar', - 'baz': 'biz' - }; - element = $compile('
')($rootScope); - $rootScope.$digest(); - expect(controllerCalled).toBe(true); - }); - }); + templateOptions = [{ + description: 'inline template', + template: '

template

' + }, { + description: 'templateUrl setting', + templateUrl: 'test.html' + }, { + description: 'no template' + }]; + forEach(controllerOptions, function(controllerOption) { + forEach(scopeOptions, function(scopeOption) { + forEach(templateOptions, function(templateOption) { + + var description = [], + ddo = { + bindToController: { + 'data': '=dirData', + 'oneway': 'template

'); + $rootScope.fn = valueFn('called!'); + $rootScope.whom = 'world'; + $rootScope.remoteData = { + 'foo': 'bar', + 'baz': 'biz' + }; + element = $compile('
')($rootScope); + $rootScope.$digest(); + expect(controllerCalled).toBe(true); + if (ddo.controllerAs || ddo.controller.indexOf(' as ') !== -1) { + if (ddo.scope) { + expect($rootScope.myCtrl).toBeUndefined(); + } else { + // The controller identifier was added to the containing scope. + expect($rootScope.myCtrl).not.toBeUndefined(); + } + } + }); }); - expect(this.str).toBe('Hello, world!'); - expect(this.fn()).toBe('called!'); - }; - controllerCalled = true; - if (preAssignBindingsEnabled) { - this.check(); - } else { - this.$onInit = this.check; - } + + }); }); - $compileProvider.directive('fooDir', valueFn({ - templateUrl: 'test.html', - bindToController: { - 'data': '=dirData', - 'oneway': 'isolate

'); - $rootScope.fn = valueFn('called!'); - $rootScope.whom = 'world'; - $rootScope.remoteData = { - 'foo': 'bar', - 'baz': 'biz' - }; - element = $compile('
')($rootScope); - $rootScope.$digest(); - expect(controllerCalled).toBe(true); }); + });