diff --git a/src/ng/compile.js b/src/ng/compile.js index b333b079aa82..882df65824c5 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -989,6 +989,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { + var SIMPLE_ATTR_NAME = /^\w/; + var specialAttrHolder = document.createElement('div'); var Attributes = function(element, attributesToCopy) { if (attributesToCopy) { var keys = Object.keys(attributesToCopy); @@ -1168,7 +1170,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (value === null || isUndefined(value)) { this.$$element.removeAttr(attrName); } else { - this.$$element.attr(attrName, value); + if (SIMPLE_ATTR_NAME.test(attrName)) { + this.$$element.attr(attrName, value); + } else { + setSpecialAttr(this.$$element[0], attrName, value); + } } } @@ -1221,6 +1227,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } }; + function setSpecialAttr(element, attrName, value) { + // Attributes names that do not start with letters (such as `(click)`) cannot be set using `setAttribute` + // so we have to jump through some hoops to get such an attribute + // https://github.com/angular/angular.js/pull/13318 + specialAttrHolder.innerHTML = ""; + var attributes = specialAttrHolder.firstChild.attributes; + var attribute = attributes[0]; + // We have to remove the attribute from its container element before we can add it to the destination element + attributes.removeNamedItem(attribute.name); + attribute.value = value; + element.attributes.setNamedItem(attribute); + } function safeAddClass($element, className) { try { diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index ee09676bc4dd..069bdec48639 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -868,6 +868,17 @@ describe('$compile', function() { expect(div.attr('id')).toEqual('myid'); })); + + it('should correctly merge attributes that contain special characters', inject(function($compile, $rootScope) { + element = $compile( + '
')($rootScope); + var div = element.find('div'); + expect(div.attr('(click)')).toEqual('doSomething()'); + expect(div.attr('[value]')).toEqual('someExpression'); + expect(div.attr('ω')).toEqual('omega'); + })); + + it('should prevent multiple templates per element', inject(function($compile) { try { $compile('
');