Skip to content

Commit 1de0bee

Browse files
committed
feat(ngAria): add support for ngReadonly
handle aria-readonly based on ng-readonly feat angular#14077
1 parent 32feb2b commit 1de0bee

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

src/ngAria/aria.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
* For ngAria to do its magic, simply include the module `ngAria` as a dependency. The following
1818
* directives are supported:
19-
* `ngModel`, `ngChecked`, `ngRequired`, `ngValue`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`,
19+
* `ngModel`, `ngChecked`, `ngReadonly`, `ngRequired`, `ngValue`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`,
2020
* `ngDblClick`, and `ngMessages`.
2121
*
2222
* Below is a more detailed breakdown of the attributes handled by ngAria:
@@ -25,8 +25,9 @@
2525
* |---------------------------------------------|----------------------------------------------------------------------------------------|
2626
* | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required, input roles |
2727
* | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled |
28-
* | {@link ng.directive:ngRequired ngRequired} | aria-required |
29-
* | {@link ng.directive:ngChecked ngChecked} | aria-checked |
28+
* | {@link ng.directive:ngRequired ngRequired} | aria-required
29+
* | {@link ng.directive:ngChecked ngChecked} | aria-checked
30+
* | {@link ng.directive:ngReadonly ngReadonly} | aria-readonly ||
3031
* | {@link ng.directive:ngValue ngValue} | aria-checked |
3132
* | {@link ng.directive:ngShow ngShow} | aria-hidden |
3233
* | {@link ng.directive:ngHide ngHide} | aria-hidden |
@@ -91,6 +92,7 @@ function $AriaProvider() {
9192
var config = {
9293
ariaHidden: true,
9394
ariaChecked: true,
95+
ariaReadonly: true,
9496
ariaDisabled: true,
9597
ariaRequired: true,
9698
ariaInvalid: true,
@@ -108,6 +110,7 @@ function $AriaProvider() {
108110
*
109111
* - **ariaHidden** – `{boolean}` – Enables/disables aria-hidden tags
110112
* - **ariaChecked** – `{boolean}` – Enables/disables aria-checked tags
113+
* - **ariaReadonly** – `{boolean}` – Enables/disables aria-readonly tags
111114
* - **ariaDisabled** – `{boolean}` – Enables/disables aria-disabled tags
112115
* - **ariaRequired** – `{boolean}` – Enables/disables aria-required tags
113116
* - **ariaInvalid** – `{boolean}` – Enables/disables aria-invalid tags
@@ -209,6 +212,9 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
209212
.directive('ngChecked', ['$aria', function($aria) {
210213
return $aria.$$watchExpr('ngChecked', 'aria-checked', nodeBlackList, false);
211214
}])
215+
.directive('ngReadonly', ['$aria', function($aria) {
216+
return $aria.$$watchExpr('ngReadonly', 'aria-readonly', nodeBlackList, false);
217+
}])
212218
.directive('ngRequired', ['$aria', function($aria) {
213219
return $aria.$$watchExpr('ngRequired', 'aria-required', nodeBlackList, false);
214220
}])

test/ngAria/ariaSpec.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,52 @@ describe('$aria', function() {
396396
});
397397
});
398398

399+
describe('aria-readonly', function() {
400+
beforeEach(injectScopeAndCompiler);
401+
402+
they('should not attach itself to native $prop controls', {
403+
input: '<input ng-readonly="val">',
404+
textarea: '<textarea ng-readonly="val"></textarea>',
405+
select: '<select ng-readonly="val"></select>',
406+
button: '<button ng-readonly="val"></button>'
407+
}, function(tmpl) {
408+
var element = $compile(tmpl)(scope);
409+
scope.$apply('val = true');
410+
411+
expect(element.attr('readonly')).toBeDefined();
412+
expect(element.attr('aria-readonly')).toBeUndefined();
413+
});
414+
415+
it('should attach itself to custom controls', function() {
416+
compileElement('<div ng-readonly="val"></div>');
417+
expect(element.attr('aria-readonly')).toBe('false');
418+
419+
scope.$apply('val = true');
420+
expect(element.attr('aria-readonly')).toBe('true');
421+
422+
});
423+
424+
it('should not attach itself if an aria-readonly attribute is already present', function() {
425+
compileElement('<div ng-readonly="val" aria-readonly="userSetValue"></div>');
426+
427+
expect(element.attr('aria-readonly')).toBe('userSetValue');
428+
});
429+
430+
431+
it('should always set aria-readonly to a boolean value', function() {
432+
compileElement('<div ng-readonly="val"></div>');
433+
434+
scope.$apply('val = "test angular"');
435+
expect(element.attr('aria-readonly')).toBe('true');
436+
437+
scope.$apply('val = null');
438+
expect(element.attr('aria-readonly')).toBe('false');
439+
440+
scope.$apply('val = {}');
441+
expect(element.attr('aria-readonly')).toBe('true');
442+
});
443+
});
444+
399445
describe('aria-required', function() {
400446
beforeEach(injectScopeAndCompiler);
401447

0 commit comments

Comments
 (0)