diff --git a/src/ng/compile.js b/src/ng/compile.js index fee065820bc4..e5b80a582840 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -324,8 +324,9 @@ * If the `require` property is an object and `bindToController` is truthy, then the required controllers are * bound to the controller using the keys of the `require` property. This binding occurs after all the controllers * have been constructed but before `$onInit` is called. + * If the name of the required controller is the same as the local name (the key), the name can be + * omitted. For example, `{parentDir: '^^'}` is equivalent to `{parentDir: '^^parentDir'}`. * See the {@link $compileProvider#component} helper for an example of how this can be used. - * * If no such required directive(s) can be found, or if the directive does not have a controller, then an error is * raised (unless no link function is specified and the required controllers are not being bound to the directive * controller, in which case error checking is skipped). The name can be prefixed with: @@ -954,6 +955,20 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } } + function getDirectiveRequire(directive) { + var require = directive.require || (directive.controller && directive.name); + + if (!isArray(require) && isObject(require)) { + forEach(require, function(value, key) { + var match = value.match(REQUIRE_PREFIX_REGEXP); + var name = value.substring(match[0].length); + if (!name) require[key] = match[0] + key; + }); + } + + return require; + } + /** * @ngdoc method * @name $compileProvider#directive @@ -990,7 +1005,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { directive.priority = directive.priority || 0; directive.index = index; directive.name = directive.name || name; - directive.require = directive.require || (directive.controller && directive.name); + directive.require = getDirectiveRequire(directive); directive.restrict = directive.restrict || 'EA'; directive.$$moduleName = directiveFactory.$$moduleName; directives.push(directive); diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 2b64f8ae8170..b3582d897dd2 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -6268,6 +6268,89 @@ describe('$compile', function() { }); }); + it('should use the key if the name of a required controller is omitted', function() { + function ParentController() { this.name = 'Parent'; } + function ParentOptController() { this.name = 'ParentOpt'; } + function ParentOrSiblingController() { this.name = 'ParentOrSibling'; } + function ParentOrSiblingOptController() { this.name = 'ParentOrSiblingOpt'; } + function SiblingController() { this.name = 'Sibling'; } + function SiblingOptController() { this.name = 'SiblingOpt'; } + + angular.module('my', []) + .component('me', { + require: { + parent: '^^', + parentOpt: '?^^', + parentOrSibling1: '^', + parentOrSiblingOpt1: '?^', + parentOrSibling2: '^', + parentOrSiblingOpt2: '?^', + sibling: '', + siblingOpt: '?' + } + }) + .directive('parent', function() { + return {controller: ParentController}; + }) + .directive('parentOpt', function() { + return {controller: ParentOptController}; + }) + .directive('parentOrSibling1', function() { + return {controller: ParentOrSiblingController}; + }) + .directive('parentOrSiblingOpt1', function() { + return {controller: ParentOrSiblingOptController}; + }) + .directive('parentOrSibling2', function() { + return {controller: ParentOrSiblingController}; + }) + .directive('parentOrSiblingOpt2', function() { + return {controller: ParentOrSiblingOptController}; + }) + .directive('sibling', function() { + return {controller: SiblingController}; + }) + .directive('siblingOpt', function() { + return {controller: SiblingOptController}; + }); + + module('my'); + inject(function($compile, $rootScope) { + var template = + '