I have following app structure:
+--------------------------------------------+
| Parent |
|+------------------------------------------+|
|| Header ||
|| <form #headerForm="ngForm"> ||
|| ... ||
|| </form> ||
|+------------------------------------------+|
|+------------------------------------------+|
|| Content ||
|| <form #contentForm="ngForm"> ||
|| ... ||
|| ||
|| </form> ||
|| ||
|+------------------------------------------+|
+--------------------------------------------+
I would like to reset the states of the forms in the header and content from the Parent component. I tried to use @ViewChild/@ViewChildren from the parent component, but I do not know how to access the childs form refs.
So far I was forced to get a reference of the Header and Content components in the Parent and call a resetForm method:
export class ParentComponent {
@ViewChildren('componentWithForm') componentsWithForms: QueryList<unknown>;
...
this.componentsWithForms.forEach(component => (component as any).resetFormState());
@Component({
selector: 'app-header',
...
providers: [{ provide: 'componentWithForm', useExisting: forwardRef(() => HeaderComponent) }],
})
export class HeaderComponent {
@ViewChild('headerForm') headerForm: NgForm;
...
resetFormState() {
this.headerForm.reset();
}
Although this technically helps it leads to some ugly TypeScript casting - which I could work around creating a base-class ComponentWithForm, inheriting the Header/Content from it and setting the provider like
@Component({
selector: 'app-header',
...
providers: [{ provide: ComponentWithForm, useExisting: forwardRef(() => HeaderComponent) }],
})
export class HeaderComponent extends ComponentWithForm {
but I would actually like to get a direct reference to headerForm/contentForm which would save lot of hassle.
It think you could use a better solution like
@Input()/@Output()
for parent <-> child component communication. But if u want to use@ViewChild
, It will be best to start at official docs:https://angular.io/guide/lifecycle-hooks#responding-to-view-changes
EDITED:
You can make a base class for all your components with form that contains
resetFormState() {}
method implementation:And then in parent, query for
WithFormDirective
:So you can call it without type casting: