From 9b08cd8bd82eb70ae7d06a38f1f6d722cca2cc8d Mon Sep 17 00:00:00 2001 From: Steve Purcell Date: Thu, 19 Sep 2013 13:29:28 +0100 Subject: [PATCH] fix($compile): merge attributes safely to avoid upsetting IE8 Merging an with an in IE8 will automatically break because the "type" attribute may not be set automatically on in-document elements. This change makes Angular replace only unchanged attributes. Additionally, source and target attributes are only merged by concatenation if their values differ, to avoid unexpected results such as 'type="text text"'. Closes #4029 --- src/ng/compile.js | 10 +++++++--- test/ng/compileSpec.js | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index d97aeaf6e557..fea91aa6fa3f 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -383,7 +383,10 @@ function $CompileProvider($provide) { if (writeAttr !== false) { if (value === null || value === undefined) { this.$$element.removeAttr(attrName); - } else { + } else if (value !== this.$$element.attr(attrName)) { + // Set new value only if it is not already there, avoiding + // issues with IE, where certain attributes cannot be set + // on in-document elements, e.g. 'type' on this.$$element.attr(attrName, value); } } @@ -1130,8 +1133,9 @@ function $CompileProvider($provide) { // reapply the old attributes to the new element forEach(dst, function(value, key) { if (key.charAt(0) != '$') { - if (src[key]) { - value += (key === 'style' ? ';' : ' ') + src[key]; + var srcVal = src[key]; + if (srcVal && srcVal !== value) { + value += (key === 'style' ? ';' : ' ') + srcVal; } dst.$set(key, value, true, srcAttr[key]); } diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index d26438783d70..7267d9638ca1 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -489,6 +489,14 @@ describe('$compile', function() { expect(element).toBe(attr.$$element); } })); + directive('replaceWithArbitraryAttribute', valueFn({ + replace: true, + template: '
With data-foo
', + compile: function(element, attr) { + attr.$set('compiled', 'COMPILED'); + expect(element).toBe(attr.$$element); + } + })); })); @@ -538,6 +546,14 @@ describe('$compile', function() { expect(div.attr('high-log')).toEqual(''); })); + it('should preserve identical attributes when merging', inject(function($compile, $rootScope) { + element = $compile( + '
') + ($rootScope); + var div = element.find('div'); + expect(div.attr('data-foo')).toBe('bar'); + })); + it('should prevent multiple templates per element', inject(function($compile) { try { $compile('
');