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

Commit 4995d0e

Browse files
committed
fixup! feat($compile): add support for arbitrary property and event bindings
1 parent 1ba411e commit 4995d0e

File tree

2 files changed

+80
-16
lines changed

2 files changed

+80
-16
lines changed

src/ng/compile.js

+20-16
Original file line numberDiff line numberDiff line change
@@ -2336,7 +2336,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
23362336
directiveNormalize(nodeName), 'E', maxPriority, ignoreDirective);
23372337

23382338
// iterate over the attributes
2339-
for (var attr, name, nName, ngAttrName, value, ngPrefixMatch, nAttrs = node.attributes,
2339+
for (var attr, name, nName, value, ngPrefixMatch, nAttrs = node.attributes,
23402340
j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
23412341
var attrStartName = false;
23422342
var attrEndName = false;
@@ -2349,8 +2349,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
23492349
value = attr.value;
23502350

23512351
// support ng-attr-*, ng-prop-* and ng-on-*
2352-
ngAttrName = directiveNormalize(name);
2353-
if ((ngPrefixMatch = ngAttrName.match(NG_PREFIX_BINDING))) {
2352+
nName = directiveNormalize(name);
2353+
if ((ngPrefixMatch = nName.match(NG_PREFIX_BINDING))) {
23542354
isNgAttr = ngPrefixMatch[1] === 'Attr';
23552355
isNgProp = ngPrefixMatch[1] === 'Prop';
23562356
isNgEvent = ngPrefixMatch[1] === 'On';
@@ -2361,27 +2361,31 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
23612361
});
23622362

23632363
// support *-start / *-end multi element directives
2364-
} else if ((multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE)) && directiveIsMultiElement(multiElementMatch[1])) {
2364+
} else if ((multiElementMatch = nName.match(MULTI_ELEMENT_DIR_RE)) && directiveIsMultiElement(multiElementMatch[1])) {
23652365
attrStartName = name;
23662366
attrEndName = name.substr(0, name.length - 5) + 'end';
23672367
name = name.substr(0, name.length - 6);
23682368
}
23692369

2370-
nName = directiveNormalize(name.toLowerCase());
2371-
attrsMap[nName] = name;
2370+
if (isNgProp || isNgEvent) {
2371+
attrs[nName] = value;
2372+
attrsMap[nName] = attr.name;
23722373

2373-
if (isNgProp) {
2374-
attrs[ngAttrName] = value;
2375-
addPropertyDirective(node, directives, ngAttrName, name);
2376-
} else if (isNgEvent) {
2377-
attrs[ngAttrName] = value;
2378-
addEventDirective(directives, ngAttrName, name);
2374+
if (isNgProp) {
2375+
addPropertyDirective(node, directives, nName, name);
2376+
} else {
2377+
addEventDirective(directives, nName, name);
2378+
}
23792379
} else {
2380+
//Update nName for cases where a prefix was removed
2381+
nName = directiveNormalize(name.toLowerCase());
2382+
attrsMap[nName] = name;
2383+
23802384
if (isNgAttr || !attrs.hasOwnProperty(nName)) {
2381-
attrs[nName] = value;
2382-
if (getBooleanAttrName(node, nName)) {
2383-
attrs[nName] = true; // presence means true
2384-
}
2385+
attrs[nName] = value;
2386+
if (getBooleanAttrName(node, nName)) {
2387+
attrs[nName] = true; // presence means true
2388+
}
23852389
}
23862390

23872391
addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);

test/ng/compileSpec.js

+60
Original file line numberDiff line numberDiff line change
@@ -12026,6 +12026,29 @@ describe('$compile', function() {
1202612026
expect(element.attr('test3')).toBe('Misko');
1202712027
}));
1202812028

12029+
it('should use the non-prefixed name in $attr mappings', function() {
12030+
var attrs;
12031+
module(function() {
12032+
directive('attrExposer', valueFn({
12033+
link: function($scope, $element, $attrs) {
12034+
attrs = $attrs;
12035+
}
12036+
}));
12037+
});
12038+
inject(function($compile, $rootScope) {
12039+
$compile('<div attr-exposer ng-attr-title="12" ng-attr-super-title="34">')($rootScope);
12040+
$rootScope.$apply();
12041+
expect(attrs.title).toBe('12');
12042+
expect(attrs.$attr.title).toBe('title');
12043+
expect(attrs.ngAttrTitle).toBeUndefined();
12044+
expect(attrs.$attr.ngAttrTitle).toBeUndefined();
12045+
expect(attrs.superTitle).toBe('34');
12046+
expect(attrs.$attr.superTitle).toBe('super-title');
12047+
expect(attrs.ngAttrSuperTitle).toBeUndefined();
12048+
expect(attrs.$attr.ngAttrSuperTitle).toBeUndefined();
12049+
});
12050+
})
12051+
1202912052
it('should work with the "href" attribute', inject(function() {
1203012053
$rootScope.value = 'test';
1203112054
element = $compile('<a ng-attr-href="test/{{value}}"></a>')($rootScope);
@@ -12270,6 +12293,43 @@ describe('$compile', function() {
1227012293
expect(element.attr('asdf')).toBe('foo');
1227112294
}));
1227212295

12296+
it('should use the full ng-prop-* attribute name in $attr mappings', function() {
12297+
var attrs;
12298+
module(function() {
12299+
directive('attrExposer', valueFn({
12300+
link: function($scope, $element, $attrs) {
12301+
attrs = $attrs;
12302+
}
12303+
}));
12304+
});
12305+
inject(function($compile, $rootScope) {
12306+
$compile('<div attr-exposer ng-prop-title="42">')($rootScope);
12307+
$rootScope.$apply();
12308+
expect(attrs.title).toBeUndefined();
12309+
expect(attrs.$attr.title).toBeUndefined();
12310+
expect(attrs.ngPropTitle).toBe('42');
12311+
expect(attrs.$attr.ngPropTitle).toBe('ng-prop-title');
12312+
});
12313+
});
12314+
12315+
it('should not conflict with (ng-attr-)attribute mappings of the same name', function() {
12316+
var attrs;
12317+
module(function() {
12318+
directive('attrExposer', valueFn({
12319+
link: function($scope, $element, $attrs) {
12320+
attrs = $attrs;
12321+
}
12322+
}));
12323+
});
12324+
inject(function($compile, $rootScope) {
12325+
$compile('<div attr-exposer ng-prop-title="42" ng-attr-title="foo" title="bar">')($rootScope);
12326+
$rootScope.$apply();
12327+
expect(attrs.title).toBe('foo');
12328+
expect(attrs.$attr.title).toBe('title');
12329+
expect(attrs.$attr.ngPropTitle).toBe("ng-prop-title");
12330+
});
12331+
});
12332+
1227312333
it('should disallow property binding on onclick', inject(function($compile, $rootScope) {
1227412334
// All event prop bindings are disallowed.
1227512335
$rootScope.onClickJs = function() {};

0 commit comments

Comments
 (0)