angular: Regression introduced by new min max validators
Bug Report
Affected Package
@angular/forms 12+
Is this a regression?
Yes, the previous version in which this bug was not present was: 11
Description
@angular/forms 12 introduced min and max validators based on the min and max attributes presence in #39063.
Before that, the browser would react to min/max attributes by doing validation and also by preventing to introduce invalid value. Both of those native features are now impossible to leverage.
Also, before that, it was possible to deactivate the browser native features with a null value, such as [min]="null"
or [min]="undefined"
. This is now impossible to do in strict mode compilation, because the new directive only accept string | number
and would result in a compilation error. Possible temporary workaround for that is to use $any
casting similar to [min]="configuration.min ?? $any(undefined)"
Suggested fixes
I would suggest that both directives create, and maintain, the equivalent attribute on the HTMLInputElement, so that browsers are able to react accordingly and adapt their UX.
And I would suggest to loosen the input type like so:
- @Input() min!: string|number;
+ @Input() min: string|number|null|undefined;
If those suggestions sound mergeable I could create PRs for it.
Minimal Reproduction
- https://stackblitz.com/edit/min-max-regression-angular-11
- https://stackblitz.com/edit/min-max-regression-angular-12, same as above, but with strict mode disabled, and Angular 12
Exception or Error
Type 'number | null' is not assignable to type 'string | number'.
Your Environment
Angular Version:
Angular CLI: 12.0.1
Node: 14.17.0
Package Manager: yarn 1.22.5
OS: linux x64
Angular: 12.0.1
... animations, cdk, cli, common, compiler, compiler-cli, core
... forms, language-service, localize, material
... platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1200.1
@angular-devkit/build-angular 12.0.1
@angular-devkit/core 12.0.1
@angular-devkit/schematics 12.0.1
@angular/flex-layout 12.0.0-beta.34
@schematics/angular 12.0.1
ng-packagr 12.0.0
rxjs 6.6.7
typescript 4.2.4
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 18 (17 by maintainers)
Commits related to this issue
- Reproduce strict compilation failure as seen in https://github.com/angular/angular/issues/42267 — committed to PowerKiKi/angular-issue-42267 by PowerKiKi 3 years ago
- Reproduce strict compilation failure as seen in https://github.com/angular/angular/issues/42267 — committed to PowerKiKi/angular-issue-42267 by PowerKiKi 3 years ago
- fix(forms): resolved min and max validator issue Resolved min and max validator issue as it wasn't working when value was set to 0. Partially closes #42267 — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): resolved min and max validator issue Resolved min and max validator issue as it wasn't working when value was set to 0. Partially closes #42267 — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): resolved min and max validator issue Resolved min and max validator issue as it wasn't working when value was set to 0. Partially closes #42267 — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): resolved min and max validator issue Resolved min and max validator issue as it wasn't working when value was set to 0. Partially closes #42267 — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): resolved min and max validator issue Resolved min and max validator issue as it wasn't working when value was set to 0. Partially closes #42267 — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): resolved min and max validator issue Resolved min and max validator issue as it wasn't working when value was set to 0. Partially closes #42267 — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): the `min` and `max` validators should work correctly with `0` as a value Prior to this change the `min` and `max` validator directives would not set the `min` and `max` attributes on the ... — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): the `min` and `max` validators should work correctly with `0` as a value (#42412) Prior to this change the `min` and `max` validator directives would not set the `min` and `max` attribute... — committed to angular/angular by iRealNirmal 3 years ago
- fix(forms): the `min` and `max` validators should work correctly with `0` as a value Prior to this change the `min` and `max` validator directives would not set the `min` and `max` attributes on the ... — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): allow max/min/maxlength/minlength/pattern validators to be bound to `null` If the validator is bound to `null` then no validation occurs and attribute is not added in DOM. Closes #42267 — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): allow max/min/maxlength/minlength/pattern validators to be bound to `null` If the validator is bound to `null` then no validation occurs and attribute is not added in DOM. Closes #42267 — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): allow minLength/maxLength validator to be bound to `null` If the validator is bound to be `null` then no validation occurs and attribute is not added to DOM. For every validator type dif... — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): allow minLength/maxLength validator to be bound to `null` If the validator is bound to be `null` then no validation occurs and attribute is not added to DOM. For every validator type dif... — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): allow minLength/maxLength validator to be bound to `null` If the validator is bound to be `null` then no validation occurs and attribute is not added to DOM. For every validator type dif... — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): allow minLength/maxLength validator to be bound to `null` If the validator is bound to be `null` then no validation occurs and attribute is not added to DOM. For every validator type dif... — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): allow minLength/maxLength validator to be bound to `null` If the validator is bound to be `null` then no validation occurs and attribute is not added to DOM. For every validator type dif... — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): allow minLength/maxLength validator to be bound to `null` If the validator is bound to be `null` then no validation occurs and attribute is not added to DOM. For every validator type dif... — committed to iRealNirmal/angular by iRealNirmal 3 years ago
- fix(forms): allow minLength/maxLength validator to be bound to `null` If the validator is bound to be `null` then no validation occurs and attribute is not added to DOM. For every validator type dif... — committed to iRealNirmal/angular by iRealNirmal 3 years ago
As discussed offline the
min
attribute is being removed when the value is 0 is because of thishost
binding:Hi, thanks for reporting the issue.
Just want to provide a bit more context after initial investigation. The
min
/max
validators were modeled afterminlength
/maxlength
ones, which have the input type defined asstring|number
:https://github.com/angular/angular/blob/4ac55ca676769a54a76c5881d40109b556f497b7/packages/forms/src/directives/validators.ts#L553-L554
However in the code below the input value is checked against
null
andundefined
values as well:https://github.com/angular/angular/blob/4ac55ca676769a54a76c5881d40109b556f497b7/packages/forms/src/directives/validators.ts#L569-L571
So the
minlength
andmaxlength
directives would have the same problem from types perspective, but would work as expected (no validation happening) if the value isnull
orundefined
.It looks like the
min
andmax
validators work withnull
andundefined
by accident where these values are converted toNaN
and after that the comparison with a number always givesfalse
, so the underlying minValidator and maxValidator functions return “validation is successful” result.Looking at other validator directives in the packages/forms/src/directives/validators.ts file, some of them have special checks for when validator should be enabled, such as the required validator, but in some cases (for example in the pattern validator), the validation will always happen and there is no way to conditionally enable/disable it.
My conclusion is that we should revisit all existing form validators (not only
min
andmax
) from that perspective and make sure that the logic is consistent. Specifically verify (by adding tests) that there is a way to conditionally disable validation, update input types accordingly (to allow fornull|undefined
types) and mention this behavior in docs.thanks @PowerKiKi this helped.
I would think you can workaround this issue by binding to
[attr.min]
instead, fwiw.