Skip to content

Commit ee5b7af

Browse files
committed
fix(compile): Collecting directives from tags that will be replaced
Fix the collecting of directives from elements that will get replaced by another directive on an attribute. If the element has an attribute or class directive that will replace the entire element, then do not collect the directive on the element Closes angular#2573 BREAKING CHANGE: * Will break directives that made the assumption that any directive on the replaced element would get collected * Will break directives that expect to be collected twice when they were replaced by another directive that is marked as replace
1 parent 40c36ee commit ee5b7af

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

src/ng/compile.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -510,10 +510,8 @@ function $CompileProvider($provide) {
510510

511511
switch(nodeType) {
512512
case 1: /* Element */
513-
// use the node name: <directive>
514-
addDirective(directives,
515-
directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);
516-
513+
var attributesDirectives = [];
514+
var hasReplaceAttributeDirective = false;
517515
// iterate over the attributes
518516
for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes,
519517
j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
@@ -534,7 +532,7 @@ function $CompileProvider($provide) {
534532
attrs[nName] = true; // presence means true
535533
}
536534
addAttrInterpolateDirective(node, directives, value, nName);
537-
addDirective(directives, nName, 'A', maxPriority);
535+
addDirective(attributesDirectives, nName, 'A', maxPriority);
538536
}
539537
}
540538

@@ -543,12 +541,24 @@ function $CompileProvider($provide) {
543541
if (isString(className) && className !== '') {
544542
while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
545543
nName = directiveNormalize(match[2]);
546-
if (addDirective(directives, nName, 'C', maxPriority)) {
544+
if (addDirective(attributesDirectives, nName, 'C', maxPriority)) {
547545
attrs[nName] = trim(match[3]);
548546
}
549547
className = className.substr(match.index + match[0].length);
550548
}
551549
}
550+
551+
forEach(attributesDirectives, function(directive) {
552+
hasReplaceAttributeDirective |= directive.replace;
553+
});
554+
if (!hasReplaceAttributeDirective) {
555+
// use the node name: <directive>
556+
addDirective(directives,
557+
directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);
558+
}
559+
forEach(attributesDirectives, function(directive) {
560+
directives.push(directive);
561+
});
552562
break;
553563
case 3: /* Text Node */
554564
addTextInterpolateDirective(directives, node.nodeValue);

test/ng/compileSpec.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,10 @@ describe('$compile', function() {
489489
expect(element).toBe(attr.$$element);
490490
}
491491
}));
492+
directive('replaceDirective', valueFn({
493+
replace: true,
494+
template: '<input ng-maxlength="3" />'
495+
}));
492496
}));
493497

494498

@@ -575,6 +579,19 @@ describe('$compile', function() {
575579
}));
576580

577581

582+
it('should not collect the directive from an element if the element has a' +
583+
' replace directive', inject(function($compile, $rootScope, $sniffer, $browser) {
584+
var element = $compile('<form name="form"><input ng-model="name" name="alias" replace-directive /></form>')($rootScope);
585+
586+
element.find('input').val('aaaa');
587+
browserTrigger(element.find('input'), ($sniffer.hasEvent('input')) ? 'input' : 'change');
588+
expect($rootScope.name).toBe(undefined);
589+
expect($rootScope.form.alias.$valid).toBe(false);
590+
591+
dealoc(element);
592+
}));
593+
594+
578595
it('should merge interpolated css class', inject(function($compile, $rootScope) {
579596
element = $compile('<div class="one {{cls}} three" replace></div>')($rootScope);
580597

0 commit comments

Comments
 (0)