From ee5b7afe815e250dc5e18333d5785034938dc871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Galfas=C3=B3?= Date: Thu, 9 May 2013 11:33:26 -0300 Subject: [PATCH] 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 #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 --- src/ng/compile.js | 22 ++++++++++++++++------ test/ng/compileSpec.js | 17 +++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 3933a31b4bc5..d95e01fa84a0 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -510,10 +510,8 @@ function $CompileProvider($provide) { switch(nodeType) { case 1: /* Element */ - // use the node name: - addDirective(directives, - directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority); - + var attributesDirectives = []; + var hasReplaceAttributeDirective = false; // iterate over the attributes for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes, j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { @@ -534,7 +532,7 @@ function $CompileProvider($provide) { attrs[nName] = true; // presence means true } addAttrInterpolateDirective(node, directives, value, nName); - addDirective(directives, nName, 'A', maxPriority); + addDirective(attributesDirectives, nName, 'A', maxPriority); } } @@ -543,12 +541,24 @@ function $CompileProvider($provide) { if (isString(className) && className !== '') { while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { nName = directiveNormalize(match[2]); - if (addDirective(directives, nName, 'C', maxPriority)) { + if (addDirective(attributesDirectives, nName, 'C', maxPriority)) { attrs[nName] = trim(match[3]); } className = className.substr(match.index + match[0].length); } } + + forEach(attributesDirectives, function(directive) { + hasReplaceAttributeDirective |= directive.replace; + }); + if (!hasReplaceAttributeDirective) { + // use the node name: + addDirective(directives, + directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority); + } + forEach(attributesDirectives, function(directive) { + directives.push(directive); + }); break; case 3: /* Text Node */ addTextInterpolateDirective(directives, node.nodeValue); diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 26f61357bee3..5cdd18ea1a9e 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -489,6 +489,10 @@ describe('$compile', function() { expect(element).toBe(attr.$$element); } })); + directive('replaceDirective', valueFn({ + replace: true, + template: '' + })); })); @@ -575,6 +579,19 @@ describe('$compile', function() { })); + it('should not collect the directive from an element if the element has a' + + ' replace directive', inject(function($compile, $rootScope, $sniffer, $browser) { + var element = $compile('
')($rootScope); + + element.find('input').val('aaaa'); + browserTrigger(element.find('input'), ($sniffer.hasEvent('input')) ? 'input' : 'change'); + expect($rootScope.name).toBe(undefined); + expect($rootScope.form.alias.$valid).toBe(false); + + dealoc(element); + })); + + it('should merge interpolated css class', inject(function($compile, $rootScope) { element = $compile('
')($rootScope);