Skip to content

Commit 5aaaa87

Browse files
committed
fix(ngAria): correctly set "checked" attr for checkboxes and radios
Make sure the checked attribute is set correctly for: - checkboxes with string and integer models using ngTrueValue / ngFalseValue - radios with integer models - radios with boolean models using ngValue Fixes angular#10389 Fixes angular#10212
1 parent e6a2527 commit 5aaaa87

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

src/ngAria/aria.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ function $AriaProvider() {
133133
* @name $aria
134134
*
135135
* @description
136+
* @priority 200
136137
*
137138
* The $aria service contains helper methods for applying common
138139
* [ARIA](http://www.w3.org/TR/wai-aria/) attributes to HTML directives.
@@ -216,6 +217,7 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
216217
return {
217218
restrict: 'A',
218219
require: '?ngModel',
220+
priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value
219221
link: function(scope, elem, attr, ngModel) {
220222
var shape = getShape(attr, elem);
221223
var needsTabIndex = shouldAttachAttr('tabindex', elem);
@@ -228,19 +230,19 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
228230
if (needsTabIndex) {
229231
needsTabIndex = false;
230232
return function ngAriaRadioReaction(newVal) {
231-
var boolVal = newVal === attr.value;
233+
var boolVal = (attr.value == ngModel.$viewValue);
232234
elem.attr('aria-checked', boolVal);
233235
elem.attr('tabindex', 0 - !boolVal);
234236
};
235237
} else {
236238
return function ngAriaRadioReaction(newVal) {
237-
elem.attr('aria-checked', newVal === attr.value);
239+
elem.attr('aria-checked', (attr.value == ngModel.$viewValue));
238240
};
239241
}
240242
}
241243

242244
function ngAriaCheckboxReaction(newVal) {
243-
elem.attr('aria-checked', !!newVal);
245+
elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue));
244246
}
245247

246248
switch (shape) {

test/ngAria/ariaSpec.js

+52
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,28 @@ describe('$aria', function() {
8585
expect(element.attr('aria-checked')).toBe('false');
8686
});
8787

88+
it('should handle checkbox with string model values using ng(True|False)Value', function() {
89+
var element = $compile('<input type="checkbox" ng-model="val" ng-true-value="\'yes\'">' +
90+
'ng-false-value="\'no\'"'
91+
)(scope);
92+
93+
scope.$apply('val="yes"');
94+
expect(element.eq(0).attr('aria-checked')).toBe('true');
95+
96+
scope.$apply('val="no"');
97+
expect(element.eq(0).attr('aria-checked')).toBe('false');
98+
});
99+
100+
it('should handle checkbox with integer model values using ngTrueValue', function() {
101+
var element = $compile('<input type="checkbox" ng-model="val" ng-true-value="0">')(scope);
102+
103+
scope.$apply('val=0');
104+
expect(element.eq(0).attr('aria-checked')).toBe('true');
105+
106+
scope.$apply('val=1');
107+
expect(element.eq(0).attr('aria-checked')).toBe('false');
108+
});
109+
88110
it('should attach itself to input type="radio"', function() {
89111
var element = $compile('<input type="radio" ng-model="val" value="one">' +
90112
'<input type="radio" ng-model="val" value="two">')(scope);
@@ -98,6 +120,36 @@ describe('$aria', function() {
98120
expect(element.eq(1).attr('aria-checked')).toBe('true');
99121
});
100122

123+
it('should handle radios with integer model values', function() {
124+
var element = $compile('<input type="radio" ng-model="val" value="0">' +
125+
'<input type="radio" ng-model="val" value="1">')(scope);
126+
127+
scope.$apply('val=0');
128+
expect(element.eq(0).attr('aria-checked')).toBe('true');
129+
expect(element.eq(1).attr('aria-checked')).toBe('false');
130+
131+
scope.$apply('val=1');
132+
expect(element.eq(0).attr('aria-checked')).toBe('false');
133+
expect(element.eq(1).attr('aria-checked')).toBe('true');
134+
});
135+
136+
it('should handle radios with boolean model values using ngValue', function() {
137+
var element = $compile('<input type="radio" ng-model="val" ng-value="valExp">' +
138+
'<input type="radio" ng-model="val" ng-value="valExp2">')(scope);
139+
140+
scope.$apply(function() {
141+
scope.valExp = true;
142+
scope.valExp2 = false;
143+
scope.val = true;
144+
});
145+
expect(element.eq(0).attr('aria-checked')).toBe('true');
146+
expect(element.eq(1).attr('aria-checked')).toBe('false');
147+
148+
scope.$apply('val = false');
149+
expect(element.eq(0).attr('aria-checked')).toBe('false');
150+
expect(element.eq(1).attr('aria-checked')).toBe('true');
151+
});
152+
101153
it('should attach itself to role="radio"', function() {
102154
scope.$apply("val = 'one'");
103155
compileInput('<div role="radio" ng-model="val" value="{{val}}"></div>');

0 commit comments

Comments
 (0)