Skip to content

Commit 55ac2e6

Browse files
committed
fix(ngAria): correctly set "checkd" 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 225e80d commit 55ac2e6

File tree

3 files changed

+45
-24
lines changed

3 files changed

+45
-24
lines changed

src/ng/directive/input.js

-3
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,6 @@ function radioInputType(scope, element, attr, ctrl) {
13101310
ctrl.$render = function() {
13111311
var value = attr.value;
13121312
element[0].checked = (value == ctrl.$viewValue);
1313-
dump('after render');
13141313
};
13151314

13161315
attr.$observe('value', ctrl.$render);
@@ -1340,7 +1339,6 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt
13401339
element.on('click', listener);
13411340

13421341
ctrl.$render = function() {
1343-
dump('render', typeof ctrl.$viewValue);
13441342
element[0].checked = ctrl.$viewValue;
13451343
};
13461344

@@ -1352,7 +1350,6 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt
13521350
};
13531351

13541352
ctrl.$formatters.push(function(value) {
1355-
dump('formatter', value, trueValue, equals(value, trueValue));
13561353
return equals(value, trueValue);
13571354
});
13581355

src/ngAria/aria.js

+2-8
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,26 +230,18 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
228230
if (needsTabIndex) {
229231
needsTabIndex = false;
230232
return function ngAriaRadioReaction(newVal) {
231-
// var boolVal = (angular.isUndefined(newVal) ? newVal : newVal.toString()) === attr.value;
232-
// var boolVal = !ngModel.$isEmpty(ngModel.$viewValue);
233233
var boolVal = (attr.value == ngModel.$viewValue);
234-
dump(ngModel.$viewValue, ngModel.$isEmpty(ngModel.$viewValue));
235234
elem.attr('aria-checked', boolVal);
236235
elem.attr('tabindex', 0 - !boolVal);
237236
};
238237
} else {
239238
return function ngAriaRadioReaction(newVal) {
240-
// elem.attr('aria-checked', (!ngModel.$isEmpty(ngModel.$viewValue)));
241-
dump('no needs tabindex', ngModel.$viewValue, ngModel.$isEmpty(ngModel.$viewValue));
242-
// elem.attr('aria-checked', (angular.isUndefined(newVal) ? newVal : newVal.toString()) === attr.value);
243239
elem.attr('aria-checked', (attr.value == ngModel.$viewValue));
244240
};
245241
}
246242
}
247243

248244
function ngAriaCheckboxReaction(newVal) {
249-
// elem.attr('aria-checked', !!newVal);
250-
dump('checkbox', newVal, ngModel.$viewValue, ngModel.$isEmpty(ngModel.$viewValue));
251245
elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue));
252246
}
253247

test/ngAria/ariaSpec.js

+43-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
ddescribe('$aria', function() {
3+
describe('$aria', function() {
44
var scope, $compile, element;
55

66
beforeEach(module('ngAria'));
@@ -85,6 +85,28 @@ ddescribe('$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,28 +120,36 @@ ddescribe('$aria', function() {
98120
expect(element.eq(1).attr('aria-checked')).toBe('true');
99121
});
100122

101-
it('should handle non-string model values for checkbox', function() {
102-
var element = $compile('<input type="checkbox" ng-model="val" ng-true-value="0">')(scope);
123+
124+
it('should handle radios with integer model values', function() {
125+
var element = $compile('<input type="radio" ng-model="val" value="0">' +
126+
'<input type="radio" ng-model="val" value="1">')(scope);
103127

104128
scope.$apply("val=0");
105129
expect(element.eq(0).attr('aria-checked')).toBe('true');
130+
expect(element.eq(1).attr('aria-checked')).toBe('false');
106131

107-
// scope.$apply("val=1");
108-
// // dump('bla', element.controller('ngModel').$viewValue);
109-
// expect(element.eq(0).attr('aria-checked')).toBe('false');
110-
// expect(element.eq(1).attr('aria-checked')).toBe('true');
132+
scope.$apply("val=1");
133+
expect(element.eq(0).attr('aria-checked')).toBe('false');
134+
expect(element.eq(1).attr('aria-checked')).toBe('true');
111135
});
112136

113-
it('should handle non-string model values', function() {
114-
var element = $compile('<input type="radio" ng-model="val" value="0">' +
115-
'<input type="radio" ng-model="val" value="1">')(scope);
137+
it('should handle radios with boolean model values using ngValue', function() {
138+
var element = $compile('<input type="radio" ng-model="val" ng-value="valExp">' +
139+
'<input type="radio" ng-model="val" ng-value="valExp2">')(scope);
140+
141+
scope.$apply(function() {
142+
scope.valExp = true;
143+
scope.valExp2 = false;
144+
scope.val = true;
145+
});
116146

117-
scope.$apply("val=0");
118147
expect(element.eq(0).attr('aria-checked')).toBe('true');
119148
expect(element.eq(1).attr('aria-checked')).toBe('false');
120149

121-
scope.$apply("val=1");
122-
dump('bla', element.controller('ngModel').$viewValue);
150+
scope.$apply(function() {
151+
scope.val = false;
152+
});
123153
expect(element.eq(0).attr('aria-checked')).toBe('false');
124154
expect(element.eq(1).attr('aria-checked')).toBe('true');
125155
});

0 commit comments

Comments
 (0)