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

Commit

Permalink
fix(compile): properly handle false value for boolean attrs with jQuery
Browse files Browse the repository at this point in the history
jQuery skips special boolean attrs treatment in XML nodes for historical reasons
and hence AngularJS cannot freely call `.attr(attrName, false) with such
attributes. To avoid issues in XHTML, call `removeAttr` in such cases instead.

Ref jquery/jquery#4249
Fixes #16778
  • Loading branch information
mgol committed Dec 3, 2018
1 parent 0cdff42 commit 9979ebf
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/ng/compile.js
Expand Up @@ -2197,7 +2197,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
booleanKey = getBooleanAttrName(node, key),
aliasedKey = getAliasedAttrName(key),
observer = key,
nodeName;
nodeName, lowercasedName, isBooleanAttr;

if (booleanKey) {
this.$$element.prop(key, value);
Expand Down Expand Up @@ -2231,7 +2231,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
this.$$element.removeAttr(attrName);
} else {
if (SIMPLE_ATTR_NAME.test(attrName)) {
this.$$element.attr(attrName, value);
// jQuery skips special boolean attrs treatment in XML nodes for
// historical reasons and hence AngularJS cannot freely call
// `.attr(attrName, false) with such attributes. To avoid issues
// in XHTML, call `removeAttr` in such cases instead.
// See https://github.com/jquery/jquery/issues/4249
if (booleanKey && value === false) {
this.$$element.removeAttr(attrName);
} else {
this.$$element.attr(attrName, value);
}
} else {
setSpecialAttr(this.$$element[0], attrName, value);
}
Expand Down
34 changes: 34 additions & 0 deletions test/ng/compileSpec.js
Expand Up @@ -4222,6 +4222,40 @@ describe('$compile', function() {
expect(element.attr('ng-my-attr')).toBeUndefined();
});

it('should set the value to lowercased keys for boolean attrs', function() {
attr.$set('disabled', 'value');
expect(element.attr('disabled')).toEqual('disabled');

element.removeAttr('disabled');

attr.$set('dISaBlEd', 'VaLuE');
expect(element.attr('disabled')).toEqual('disabled');
});

it('should call removeAttr for boolean attrs when value is `false`', function() {
attr.$set('disabled', 'value');

spyOn(jqLite.prototype, 'attr').and.callThrough();
spyOn(jqLite.prototype, 'removeAttr').and.callThrough();

attr.$set('disabled', false);

expect(element.attr).not.toHaveBeenCalled();
expect(element.removeAttr).toHaveBeenCalledWith('disabled');
expect(element.attr('disabled')).toEqual(undefined);

attr.$set('disabled', 'value');

element.attr.calls.reset();
element.removeAttr.calls.reset();

attr.$set('dISaBlEd', false);

expect(element.attr).not.toHaveBeenCalled();
expect(element.removeAttr).toHaveBeenCalledWith('disabled');
expect(element.attr('disabled')).toEqual(undefined);
});


it('should not set DOM element attr if writeAttr false', function() {
attr.$set('test', 'value', false);
Expand Down

0 comments on commit 9979ebf

Please sign in to comment.