You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
fix(aria/ngModel): do not overwrite the default $isEmpty() method for checkboxes
Previously, `ngAria` would overwrite the default `ngModelController.$isEmpty()` method for custom
`checkbox`-shaped controls (e.g. `role="checkbox"` or `role="menuitemcheckbox"`), using the same
implementation as `input[checkbox]` (i.e. `value === false`). While this makes sense for
`input[checkbox]` which also defines a custom parser, it doesn't make sense for a custom `checkbox`
out-of-the-box. For example, an unintialized value (`undefined`) would make the checkbox appear as
"checked".
If the user wants to provide a custom parser (e.g. setting falsy values to `false`), then they
should also provide a custom `$isEmpty()` method.
As a side effect, this commit solves issue #14621. (We could have solved it in different ways.)
Fixes#14621Closes#14625
BREAKING CHANGE:
Custom `checkbox`-shaped controls (e.g. checkboxes, menuitemcheckboxes), no longer have a custom
`$isEmpty()` method on their `NgModelController` that checks for `value === false`. Unless
overwritten, the default `$isEmpty()` method will be used, which treats `undefined`, `null`, `NaN`
and `''` as "empty".
**Note:** The `$isEmpty()` method is used to determine if the checkbox is checked ("not empty" means
"checked") and thus it can indirectly affect other things, such as the control's validity
with respect to the `required` validator (e.g. "empty" + "required" --> "invalid").
Before:
```js
var template = '<my-checkbox role="checkbox" ng-model="value"></my-checkbox>';
var customCheckbox = $compile(template)(scope);
var ctrl = customCheckbox.controller('ngModel');
scope.$apply('value = false');
console.log(ctrl.$isEmpty()); //--> true
scope.$apply('value = true');
console.log(ctrl.$isEmpty()); //--> false
scope.$apply('value = undefined'/* or null or NaN or '' */);
console.log(ctrl.$isEmpty()); //--> false
```
After:
```js
var template = '<my-checkbox role="checkbox" ng-model="value"></my-checkbox>';
var customCheckbox = $compile(template)(scope);
var ctrl = customCheckbox.controller('ngModel');
scope.$apply('value = false');
console.log(ctrl.$isEmpty()); //--> false
scope.$apply('value = true');
console.log(ctrl.$isEmpty()); //--> false
scope.$apply('value = undefined'/* or null or NaN or '' */);
console.log(ctrl.$isEmpty()); //--> true
```
--
If you want to have a custom `$isEmpty()` method, you need to overwrite the default. For example:
```js
.directive('myCheckbox', function myCheckboxDirective() {
return {
require: 'ngModel',
link: function myCheckboxPostLink(scope, elem, attrs, ngModelCtrl) {
ngModelCtrl.$isEmpty = function myCheckboxIsEmpty(value) {
return !value; // Any falsy value means "empty"
// Or to restore the previous behavior:
// return value === false;
};
}
};
})
```
0 commit comments