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

Commit 27486bd

Browse files
committed
fix(compile): properly handle false value for boolean attrs with jQuery
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 Closes #16779
1 parent cf919a6 commit 27486bd

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

src/ng/compile.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -2231,7 +2231,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
22312231
this.$$element.removeAttr(attrName);
22322232
} else {
22332233
if (SIMPLE_ATTR_NAME.test(attrName)) {
2234-
this.$$element.attr(attrName, value);
2234+
// jQuery skips special boolean attrs treatment in XML nodes for
2235+
// historical reasons and hence AngularJS cannot freely call
2236+
// `.attr(attrName, false) with such attributes. To avoid issues
2237+
// in XHTML, call `removeAttr` in such cases instead.
2238+
// See https://github.com/jquery/jquery/issues/4249
2239+
if (booleanKey && value === false) {
2240+
this.$$element.removeAttr(attrName);
2241+
} else {
2242+
this.$$element.attr(attrName, value);
2243+
}
22352244
} else {
22362245
setSpecialAttr(this.$$element[0], attrName, value);
22372246
}

test/ng/compileSpec.js

+34
Original file line numberDiff line numberDiff line change
@@ -4222,6 +4222,40 @@ describe('$compile', function() {
42224222
expect(element.attr('ng-my-attr')).toBeUndefined();
42234223
});
42244224

4225+
it('should set the value to lowercased keys for boolean attrs', function() {
4226+
attr.$set('disabled', 'value');
4227+
expect(element.attr('disabled')).toEqual('disabled');
4228+
4229+
element.removeAttr('disabled');
4230+
4231+
attr.$set('dISaBlEd', 'VaLuE');
4232+
expect(element.attr('disabled')).toEqual('disabled');
4233+
});
4234+
4235+
it('should call removeAttr for boolean attrs when value is `false`', function() {
4236+
attr.$set('disabled', 'value');
4237+
4238+
spyOn(jqLite.prototype, 'attr').and.callThrough();
4239+
spyOn(jqLite.prototype, 'removeAttr').and.callThrough();
4240+
4241+
attr.$set('disabled', false);
4242+
4243+
expect(element.attr).not.toHaveBeenCalled();
4244+
expect(element.removeAttr).toHaveBeenCalledWith('disabled');
4245+
expect(element.attr('disabled')).toEqual(undefined);
4246+
4247+
attr.$set('disabled', 'value');
4248+
4249+
element.attr.calls.reset();
4250+
element.removeAttr.calls.reset();
4251+
4252+
attr.$set('dISaBlEd', false);
4253+
4254+
expect(element.attr).not.toHaveBeenCalled();
4255+
expect(element.removeAttr).toHaveBeenCalledWith('disabled');
4256+
expect(element.attr('disabled')).toEqual(undefined);
4257+
});
4258+
42254259

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

0 commit comments

Comments
 (0)