Parent and Child component using formGroupName directive

Viewed 34

I have a parent component with a simple form using standard HTML inputs and a custom input component:

Parent component:

<div [formGroup]="form">

    <div formGroupName="test">

        <input type="text" formControlName="testControl1">
        <input type="text" formControlName="testControl2">

        <my-input id="testControl3"></my-input> 
    </div>

Parent component form definition:

this.form = this.formBuilder.group({

      test:this.formBuilder.group({
        testControl1:['1'],
        testControl2:['2'],
        testControl3:['3'],
      })

Child component

@Component({
  selector: 'my-input',
  template: ' <input type="text" [formControlName]="id">',
})
export class MyInputComponent  { 

  @Input() id: string;
}

For the first two text there are no problems, they works as expected; my custom component explodes with the following error:

ERROR Error: formControlName must be used with a parent formGroup directive.  You'll want to add a formGroup
      directive and pass it an existing FormGroup instance (you can create one in your class).

How can I retrieve formGroupName="test" context inside my component? Do I need to pass FormGroup and FormGroupName? I'm missing something?

1 Answers

you need to use ControlValueAccessor - inside your MyInputComponent add this provider to your component config

@Component({
  selector: 'app-input',
  templateUrl: './input.component.html',
  styleUrls: ['./input.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MyInputComponent),
      multi: true
    }
  ]
})

also your component needs to implement ControlValueAccessor and the method belong to this interface

export class InputComponent implements OnInit , ControlValueAccessor {

  constructor() { }

  ngOnInit(): void {
  }
  onChange: any = () => {}
  onTouch: any = () => {}

  writeValue(value: any){
  }

  registerOnChange(fn: any){
    this.onChange = fn
  }

  registerOnTouched(fn: any){
    this.onTouch = fn
  }
   }
Related