Description
Which @angular/* package(s) are relevant/related to the feature request?
forms
Description
Several libraries (like ngx-valdemort or angular material) use the submitted
property of the parent formGroupDirective in order to decide whether or not to display error messages. This works fine as long as the form group directive is only used on the top-level form, and not for nested form groups.
See this working example, using formGroupName for the nested form group and this non-working example, using formGroup for the nested form group.
One might say that using formGroupName is an easy-enough alternative but
- with typed forms, it's less type-safe
- it is possible, but more complex, to use it from a child component, because it requires a parent formGroupDirective in the same template, unless a view provider is specified for ControlContainer, but that's far from easy to find out, and has its limitations. AFAIK, most people pass the FormGroup as input to the child component, which then uses the formGroup directive.
Proposed solution
There are several solutions I can see
- being able, from the formGroupDirective, to navigate to its parent, recursively, until getting to the top-level one which contains the correct submitted value
- Add some additional topLevelFormGroup directive, which could use the new directive composition API, and which would get a reference to the formGroupDirective on the same host to give access to it. This TopLevelFormGroupDirective could then be injected in place of the FormGroupDirective to get direct access to the submitted flag
- Have the formGroupDirective store the submitted flag in its form group, just like it's done for similar flages such as touched, dirty. Since FormGroups do have a reference to their parent, libraries needing to access the submitted property could easily navigate to the top-level directive
- ???
The third solution seems like the most logical to me. It has the additional advantage that it could allow FormGroup.reset()
to also reset the submitted flag, just as it resets the touched flags.
Alternatives considered
Clearly document that formGroupDirective is only ever supposed to be used for the top-level form (some parts of the doc suggest that, like the documentation of the path
property of FormGroupDirective, but on the other hands, I've seen many usages of the formGroupDirective in the wild for nested form groups), and clearly document how to best delegate the display of a nested form group to a child component, using formGroupName
. The best solution I've found is to use the following in the parent component:
<div formGroupName="address">
<app-address></app-address>
</div>
and use this in the decorator of the child component to be able to access the parent form group name:
viewProviders: [{ provide: ControlContainer, useExisting: FormGroupName }]
But this solution isn't without problems. For example: it forces every usage of address to be inside a formGroupName. It can't be used directly under a formGroupDirective. It's also not obvious at all.