Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 260f993

Browse files
Caitlin Pottercaitp
Caitlin Potter
authored andcommitted
feat($compile): optionally get controllers from ancestors only
Implement option to strengthen require '^' operator, by adding another '^'. When a second '^' is used, the controller will only search parent nodes for the matching controller, and will throw or return null if not found, depending on whether or not the requirement is optional. Closes #4518
1 parent 5850e61 commit 260f993

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

src/ng/compile.js

+16-8
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
502502
var hasDirectives = {},
503503
Suffix = 'Directive',
504504
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
505-
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/;
505+
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
506+
REQUIRE_PREFIX_REGEXP = /(\?)|(\^\^?)/g,
507+
REQUIRE_PREFIX_PRE_REGEXP = /^((\?)|(\^\^?))+/;
506508

507509
// Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
508510
// The assumption is that future DOM event attribute names will begin with
@@ -1343,21 +1345,27 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
13431345

13441346

13451347
function getControllers(require, $element, elementControllers) {
1346-
var value, retrievalMethod = 'data', optional = false;
1348+
var value, retrievalMethod = 'data', optional = false, search = $element, prematch, match;
13471349
if (isString(require)) {
1348-
while((value = require.charAt(0)) == '^' || value == '?') {
1349-
require = require.substr(1);
1350-
if (value == '^') {
1351-
retrievalMethod = 'inheritedData';
1350+
if ((prematch = require.match(REQUIRE_PREFIX_PRE_REGEXP)) &&
1351+
(match = prematch[0].match(REQUIRE_PREFIX_REGEXP))) {
1352+
for (var i=0, ii=match.length; i<ii; ++i) {
1353+
value = match[i];
1354+
switch (value) {
1355+
case '^': retrievalMethod = 'inheritedData'; break;
1356+
case '^^': retrievalMethod = 'inheritedData'; search = $element.parent(); break;
1357+
case '?': optional = true; break;
1358+
}
13521359
}
1353-
optional = optional || value == '?';
1360+
1361+
require = require.substring(prematch[0].length);
13541362
}
13551363
value = null;
13561364

13571365
if (elementControllers && retrievalMethod === 'data') {
13581366
value = elementControllers[require];
13591367
}
1360-
value = value || $element[retrievalMethod]('$' + require + 'Controller');
1368+
value = value || search[retrievalMethod]('$' + require + 'Controller');
13611369

13621370
if (!value && !optional) {
13631371
throw $compileMinErr('ctreq',

test/ng/compileSpec.js

+37
Original file line numberDiff line numberDiff line change
@@ -2680,6 +2680,43 @@ describe('$compile', function() {
26802680
});
26812681

26822682

2683+
it('should get required parent controller', function() {
2684+
module(function() {
2685+
directive('nested', function(log) {
2686+
return {
2687+
require: '^^?nested',
2688+
controller: function($scope) {},
2689+
link: function(scope, element, attrs, controller) {
2690+
log(!!controller);
2691+
}
2692+
};
2693+
});
2694+
});
2695+
inject(function(log, $compile, $rootScope) {
2696+
element = $compile('<div nested><div nested></div></div>')($rootScope);
2697+
expect(log).toEqual('true; false');
2698+
});
2699+
});
2700+
2701+
2702+
it('should throw if required parent is not found', function() {
2703+
module(function() {
2704+
directive('nested', function() {
2705+
return {
2706+
require: '^^nested',
2707+
controller: function($scope) {},
2708+
link: function(scope, element, attrs, controller) {}
2709+
};
2710+
});
2711+
});
2712+
inject(function($compile, $rootScope) {
2713+
expect(function() {
2714+
element = $compile('<div nested></div>')($rootScope);
2715+
}).toThrowMinErr('$compile', 'ctreq', "Controller 'nested', required by directive 'nested', can't be found!");
2716+
});
2717+
})
2718+
2719+
26832720
it('should get required controller via linkingFn (template)', function() {
26842721
module(function() {
26852722
directive('dirA', function() {

0 commit comments

Comments
 (0)