Skip to content

Commit 040c30c

Browse files
committed
fix($compile): allow directives to have interceptors
Allow directives to have interceptors that modify the directive `scope` property Close: angular#10149
1 parent d00299d commit 040c30c

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-6
lines changed

src/ng/compile.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -778,13 +778,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
778778
// The assumption is that future DOM event attribute names will begin with
779779
// 'on' and be composed of only English letters.
780780
var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
781+
var bindingCache = createMap();
781782

782783
function parseIsolateBindings(scope, directiveName, isController) {
783784
var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
784785

785786
var bindings = {};
786787

787788
forEach(scope, function(definition, scopeName) {
789+
if (definition in bindingCache) {
790+
bindings[scopeName] = bindingCache[definition];
791+
return;
792+
}
788793
var match = definition.match(LOCAL_REGEXP);
789794

790795
if (!match) {
@@ -802,6 +807,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
802807
optional: match[3] === '?',
803808
attrName: match[4] || scopeName
804809
};
810+
if (match[4]) {
811+
bindingCache[definition] = bindings[scopeName];
812+
}
805813
});
806814

807815
return bindings;
@@ -894,11 +902,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
894902
directive.name = directive.name || name;
895903
directive.require = directive.require || (directive.controller && directive.name);
896904
directive.restrict = directive.restrict || 'EA';
897-
var bindings = directive.$$bindings =
898-
parseDirectiveBindings(directive, directive.name);
899-
if (isObject(bindings.isolateScope)) {
900-
directive.$$isolateBindings = bindings.isolateScope;
901-
}
902905
directive.$$moduleName = directiveFactory.$$moduleName;
903906
directives.push(directive);
904907
} catch (e) {
@@ -2316,6 +2319,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
23162319
if (startAttrName) {
23172320
directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
23182321
}
2322+
var bindings = directive.$$bindings =
2323+
parseDirectiveBindings(directive, directive.name);
2324+
if (isObject(bindings.isolateScope)) {
2325+
directive.$$isolateBindings = bindings.isolateScope;
2326+
}
23192327
tDirectives.push(directive);
23202328
match = directive;
23212329
}

test/ng/compileSpec.js

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4194,7 +4194,7 @@ describe('$compile', function() {
41944194
dealoc(element);
41954195
compile('<div><span my-component>');
41964196
expect(componentScope).not.toBe(firstComponentScope);
4197-
expect(componentScope.$$isolateBindings).toBe(first$$isolateBindings);
4197+
expect(componentScope.$$isolateBindings).toEqual(first$$isolateBindings);
41984198
}));
41994199

42004200

@@ -7459,6 +7459,51 @@ describe('$compile', function() {
74597459
});
74607460
});
74617461

7462+
7463+
it('should be possible to change the scope of a directive using $provide', function() {
7464+
module(function($provide) {
7465+
directive('foo', function() {
7466+
return {
7467+
scope: {},
7468+
template: '<div></div>'
7469+
};
7470+
});
7471+
$provide.decorator('fooDirective', function($delegate) {
7472+
var directive = $delegate[0];
7473+
directive.scope.something = '=';
7474+
directive.template = '<span>{{something}}</span>';
7475+
return $delegate;
7476+
});
7477+
});
7478+
inject(function($compile, $rootScope) {
7479+
element = $compile('<div><div foo something="bar"></div></div>')($rootScope);
7480+
$rootScope.bar = 'bar';
7481+
$rootScope.$digest();
7482+
expect(element.text()).toBe('bar');
7483+
});
7484+
});
7485+
7486+
7487+
it('should distinguish different bindings with the same binding name', function() {
7488+
module(function() {
7489+
directive('foo', function() {
7490+
return {
7491+
scope: {
7492+
foo: '=',
7493+
bar: '='
7494+
},
7495+
template: '<div><div>{{foo}}</div><div>{{bar}}</div></div>'
7496+
};
7497+
});
7498+
});
7499+
inject(function($compile, $rootScope) {
7500+
element = $compile('<div><div foo="\'foo\'" bar="\'bar\'"></div></div>')($rootScope);
7501+
$rootScope.$digest();
7502+
expect(element.text()).toBe('foobar');
7503+
});
7504+
});
7505+
7506+
74627507
it('should safely create transclude comment node and not break with "-->"',
74637508
inject(function($rootScope) {
74647509
// see: https://github.com/angular/angular.js/issues/1740

0 commit comments

Comments
 (0)