2

I need to inject the form from a parent component into a child component to be able to validate the child component input like so:

    <form #formReference="ngForm">
     <child-component></child-component>
     <child-component></child-component>
     <child-component></child-component>

     <p>{{formReference.form.valid}}</p>
    </form>

Right now i have added this provider on the child component to make it use the parent form and it works fine

@Component({
  selector: 'app-child-component',
  templateUrl: './child-component.component.html',
  styleUrls: ['./child-component.component.scss'],
  viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]
}) 

However i still need to be able to use the child component as before without a form. Is there a way to make this provider optional? At the moment if a use my child component without a form wrapping it i get the error

ERROR NullInjectorError: R3InjectorError(CustomModule)[NgForm -> NgForm -> NgForm -> NgForm -> NgForm]
  

Thanks for your time!

navnath
  • 3,548
  • 1
  • 11
  • 19
Mirco
  • 33
  • 6

2 Answers2

6

use useFactory method to provide optional dependency, by setting Optional flag in deps array

@Component({
  selector: 'app-child-component',
  templateUrl: './child-component.component.html',
  styleUrls: ['./child-component.component.scss'],
  viewProviders: [
    {
      provide: ControlContainer,
      deps: [[Optional, NgForm]],
      useFactory: (ngForm: NgForm) => ngForm,
    },
  ],
})
Chellappan வ
  • 23,645
  • 3
  • 29
  • 60
  • Great solution, it resolves NullInjectorError. But in that parent component with form I have got another error: ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions. Any idea how to fix it? – tiger Dec 06 '21 at 12:39
  • Have you added name attribute on the input element? – Chellappan வ Dec 06 '21 at 15:33
0

In child component remove providers and inject NgControl directly via constructor using @Optional and @Self

constructor(@Optional() @Self() public ngControl: NgControl) {
   if (this.ngControl != null) this.ngControl.valueAccessor = this;
}
navnath
  • 3,548
  • 1
  • 11
  • 19