angular
angular copied to clipboard
Reactive form control `root` points to nothing or itself.
Which @angular/* package(s) are the source of the bug?
forms
Is this a regression?
No
Description
We need to have a validator for simple FormControl
to compare multiple FormGroup
values as well. Trying to reach that in two ways:
- Use
control.parent.parent.parent
(doesn't look good); - Use
control.root.get(*path*)
.
However, both options have bug. Let's talk about latter one. root
is either falsy or equal to control
(points to itself) value. So, we had to add such workaround
// In case form hasn't initialized
if (control.root == null || control.root === control) {
return null;
}
*Validation logic here*
But that doesn't work as expected because now form controls aren't validated on form init because of such workaround. How can we avoid such behavior?
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
No response
Please provide the environment you discovered this bug in (run ng version
)
Angular CLI: 14.0.4
Node: 14.17.5
Package Manager: yarn 1.22.18
OS: win32 x64
Angular: 14.0.4
... animations, cdk, cli, common, compiler, compiler-cli, core
... forms, language-service, material, platform-browser
... platform-browser-dynamic, router
Package Version
------------------------------------------------------------
@angular-devkit/architect 0.1400.4
@angular-devkit/build-angular 14.0.4
@angular-devkit/build-ng-packagr 0.1002.0
@angular-devkit/core 14.0.4
@angular-devkit/schematics 14.0.4
@angular/flex-layout 14.0.0-beta.40
@schematics/angular 14.0.4
rxjs 7.5.5
typescript 4.6.3
Anything else?
No response
Hello! I am not entirely clear on what you're trying to do. Would you be able to provide a reproduction and example on StackBlitz?
@dylhunn , here https://stackblitz.com/edit/angular-wkpmz4?file=src/app/app.component.ts
This is the best I could achieve in short amount of time. If you comment these lines validator won't work anymore
And in our case (not in the repro) when items are added with some delay the validator doesn't work correctly initially for some reason..
Also, if you remove 1
from form field, the error will disappear, but if you enter it again the error won't get back. The state will remain valid.
I was trying to analyse this issue and I think this is not a bug (however, I don't think this particular case is mentioned in docs). I've also noticed that AbstractControl.root
doesn't seem to have unit tests that would cover only this feature (but it might be covered by other unit tests).
AbstractControl.root always returns a value. Either itself or its root control so it should never be false
or null
(although it might (?) in the past since this issue was created for Angular 12). The docs isn't very clear because it doesn't mention that root
can also return the control itself if there're no parents.
https://github.com/angular/angular/blob/15.0.4/packages/forms/src/model/abstract_model.ts#L1262-L1270
What happens in the stackblitz above is that it creates FormControl
s with validators like:
new FormGroup({
key: new FormControl(itemKey, uniqueKeyValidator),
somethingElse: new FormControl(),
})
This means that it first creates a form control new FormControl(itemKey, uniqueKeyValidator)
that executes the validation function and then adds the control into its parent group FormGroup
. In other words, the first validation is executed before the FormControl
is added to FormGroup
and that's why control.root === control
.
If you re-run the validation with something like f.get('g1.0.c1')?.updateValueAndValidity();
the control c1
will have correct parent.
Updated demo for Angular 15: https://stackblitz.com/edit/angular-wkpmz4?file=src%2Fapp%2Fapp.component.scss,tsconfig.json,src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.module.ts,src%2Fapp%2Fapp.component.ts
control has a property "parant" and you can use parent instead of root https://angular.io/api/forms/FormControl
// I think this could works if (control.parent == null || control.parent === control) { return null; }