Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 260f993

Browse files
Caitlin Pottercaitp
Caitlin Potter
authored andcommittedFeb 4, 2014
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 angular#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)
Please sign in to comment.