Reputation: 5360
While building more complex reactive forms I stumbled across an issue while nesting reactiveFormGroups more than once.
So I've got two scenarios:
Form Component -> Form Partial Component -> Custom Input Component
Form Component -> Custom Input Component
The goal is to listen to the ngSubmit event in the custom input component to show its error state.
In my custom input component I'am injecting the ReactiveFormsDirective via the @Host() decorator. However if the component is nested as in scenario 1, it never receives any events.
My guess is that the problem in this scenario is related to "wrong" ControlContainer it tries to get a hold of. @Host() just looks up the injector chain until it reaches the host and not further. However this FormControlDirective doesn't know anything about the form submission.
If this was true, I'd try to pass the ControlContainer to the partial component to make it available to the input component.
viewProviders: [ { provide: ControlContainer, useExisting: FormGroupDirective } ]
Unfortunately, this doesn't work as expected.
To make this more tangible I've created a basic example here: https://stackblitz.com/edit/angular-7rmpvt
Would be great to get some help here on why this behaves the way it does and how to create a nice solution.
Upvotes: 4
Views: 1064
Reputation: 214315
As Kara said, the main idea when working with complex reactive forms is that we should define only one [formGroup] directive on a top-level.
For nested FormGroups, you'd want to use formGroupName instead to ensure that the nested group value and validation status are properly synced to the parent group's value and validation status, among other things.
So if you do have a nested [formGroup], it typically indicates that you have a nested form that is not related to the parent form. It's another top-level form that will not be connected to its parent's model. This is a relatively common pattern because, for CSS / positioning reasons, you might have a sub-form that happens to be within the form tags of another form, but is unrelated (e.g. a shopping checkout form with a "newsletter sign-up" sub form).
https://github.com/angular/angular/issues/21263#issuecomment-357074997
There's also opened issue https://github.com/angular/angular/issues/21823
With this in mind, we can fix your issue as you mentioned through providing ControlContainer
AppComponent [formGroup]
||
\/
FormPartialComponent
1) add viewProviders: [ { provide: ControlContainer, useExisting: FormGroupDirective } ]
2) remove [formGroup]
||
\/
FormInputComponent
remove @Host
This way we can easily use formControlName within FormPartialComponent and FormInputComponent will get top-level FormGroupDirective
.
To make this more tangible I've updated your Stackblitz Example
See also:
Upvotes: 3