angularangular-formsangular-content-projection

Reference ngForm between ng-content blocks and outside form


I am using a component on which there are 2 elements. In one I inject a form like so:

<form #form="ngForm">

In the other I have buttons on which I'd like to use form.valid and form.pristine like this:

<button [disabled]="!form.valid || form.pristine">

This does not work since the button lives outside the form itself and in a separate ng-content element (that part might be irrelevant).

I've tried using:

@ViewChild('form') form!: ngForm

Unfortunately, this ends up as undefined.

Thanks!


Solution

  • You are on the right track, we can just do a view child, but the value will get set only on ngAfterViewInit, so we can store the reference to the viewchild on a service variable, then use this variable to lookup the values on our not related component

    Create a service:

    export class SomeService {
        refForm!: Form;
    }
    

    In the component where the form is located

    @ViewChild('form', {static: false}) form!: ngForm; 
    ...
    
    ...
    constructor(private someService: SomeService) {}
    ...
    
    ...
    ngAfterViewInit() {
        this.someService.refForm = this.form;
    }
    ...
    

    Finally, in the component where you project the content for the button

    in the TS file add the getter method which will relay the form for checking

    ...
    
    ...
    constructor(private someService: SomeService) {}
    ...
    
    ...
    get form() {
        return this.someService.refForm;
    }
    

    component html ( Make sure to add the safe check ?. so that there are no errors if the form is undefined! )

    <button [disabled]="!form?.valid || form?.pristine">