question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Form is invalid when all fields are disabled

See original GitHub issue

🐞 bug report

Affected Package

@angular/forms

Is this a regression?

Not as far as I know. I know it happens on 9.1.11 and on 10.0.9

Description

According to the documentation:

Disabled controls are exempt from validation checks and are not included in the aggregate value of their ancestor controls.

But when all the controls in a group is disabled, the disabled fields appear in the aggregate value, and the group is invalid.

🔬 Minimal Reproduction

https://stackblitz.com/edit/angular-ivy-2gpcd4?file=src/app/app.component.ts

In this example, I have three forms, with no validators specified:

  • form1 has no fields at all. Its value is an empty object and the form is valid. This is as expected.
  • form2 has one enabled field and one disabled one (added in ngOnInit). It works exactly as documented, e.g. the form value does not contain the disabled field, and the form is valid.
  • form3 contains only the disabled field (added in ngOnInit). Its value contains the disabled field and the form is invalid. This is the opposite of the documented behavior.

🔥 Exception or Error

No exception

🌍 Your Environment

Angular Version:

The Stackblitz uses Angular 10.0.9. Below is my local environment where I first noticed it.


Angular: 9.1.11
... animations, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router, service-worker
Ivy Workspace: No

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.901.9
@angular-devkit/build-angular      0.901.9
@angular-devkit/build-ng-packagr   0.901.9
@angular-devkit/build-optimizer    0.901.9
@angular-devkit/build-webpack      0.901.9
@angular-devkit/core               9.1.9
@angular-devkit/schematics         9.1.9
@angular/cli                       9.1.9
@ngtools/webpack                   9.1.9
@schematics/angular                9.1.9
@schematics/update                 0.901.9
ng-packagr                         9.1.5
rxjs                               6.5.5
typescript                         3.8.3
webpack                            4.42.0

Anything else relevant? Nope

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
CobusKrugercommented, Oct 25, 2020

@AndrewKushnir Setting the form status back to “enabled” won’t work, because that enables all the controls. Your answer explains why the form is suddenly no longer valid. It does not explain why the value is included in the aggregate.

I investigated it further and saw that the form itself is disabled when the last of its controls is disabled. This causes the symptom I’m seeing, because in FormGroup._reduceValue, the form’s disabled is checked and vetos the control’s state:

  _reduceValue() {
    return this._reduceChildren(
        {}, (acc: {[k: string]: AbstractControl}, control: AbstractControl, name: string) => {
          if (control.enabled || this.disabled) {
            acc[name] = control.value;
          }
          return acc;
        });
  }

So if a form is disabled, its value suddenly contains the value of every contained control, valid or not. That is not correct according to the documentation, which (again) clearly states:

Disabled controls are exempt from validation checks and are not included in the aggregate value of their ancestor controls.

I can’t find it documented anywhere that a disabled form contains the aggreagate values of all its contained control. Not only is the behavior counter the documentation, but it’s also unintuitive.

1reaction
AndrewKushnircommented, Oct 29, 2020

@Michael-Ziluck thanks for the detailed answer, it makes sense 👍

I believe the confusion comes from to the fact that the enabled/disabled and valid/invalid/pending are all grouped into one field (status). We should probably consider doing a research on whether separating them at some point in the future would give benefits.

My suggestion to the Angular team is to update the documentation for the disabled to accurately mention that there is a very notable exception. It would also probably be helpful to expand on the documentation currently listed in valid and invalid to explain that invalid does not mean !valid and vice versa.

Please let us know if you have a proposal on how to improve the docs and/or you can create a PR with the proposed change - that’d be very helpful!

Thank you.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Angular Reactive Form Disabled Control is not valid
When you disabled a control, the control will be valid or not, is the form which is valid although the control is invalid....
Read more >
Valid and Invalid in Angular Forms | by Garen Stepanyan
In Angular one of most common ways to validate forms is to disable the submit button. It's a nice way (alongside with helpful...
Read more >
Exploring the difference between disabling a form control ...
I n this article, we will explore different ways to disable reactive form controls. ... Below is a simple form with two fields...
Read more >
Disabling Form Controls When Working With Reactive Forms ...
You can enable/disable a form control by using the following ways: Instantiate a new FormControl with the disabled property set to true. FormControl({value:...
Read more >
Enabling submit button only when all fields are valid
The following example will disable the Submit button as long as there is at least one invalid field. In case all of fields...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found