Search code examples
angulartypescriptformarray

Error: formGroup expects a FormGroup instance - while adding new Component to formArray


I'm using the Reactive Forms Approach. I have a form (parent component called: DeductionInvoicesComponent):

<form [formGroup]="deductionForm">
      <div formArrayName="items" class="well well-lg">
        <app-deduction-invoice-item
          *ngFor="let item of deductionForm.get('items')?.controls; let i=index"
          [index]="i"
          (removed)="deductionForm.get('items').removeAt($event)">
        </app-deduction-invoice-item>
      </div>
</form>
<button type="button" class="btn btn-primary" (click)="addItem()">Add an item</button>

The TypeScript of the parent is following:

export class DeductionInvoicesComponent implements OnInit {

  deductionForm: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.deductionForm = this.fb.group({
      items: this.fb.array([])
    });
  }

  addItem(){
    let control = <FormArray>this.deductionForm.controls.items;
    control.push(DeductionInvoiceItemComponent.buildItem());
  }
}

The form can contains multiple DeductionInvoiceItemComponents as a formArray. The child component (a single Item called: DeductionInvoiceItemComponent) looks the following:

<div class="row" [formGroup]="item">
    <div class="form-group col-4">
      <label class="center-block">Title</label>
      <select class="form-control" formControlName="title">
        <option value="test">test</option>
      </select>
    </div>
    <div class="form-group col-4">
      <label class="center-block">Invoice Number</label>
  <input class="form-control" formControlName="invoiceNumber">
</div>
<button (click)="removed.emit(index)" type="button" class="close text-danger" aria-label="Close">
  <span aria-hidden="true">&times;</span>
</button>

And the TypeScript of that single component which represents an item of the formArray looks the following:

export class DeductionInvoiceItemComponent {

  @Input()
  public index: number;

  @Input()
  public item: FormGroup;

  @Output()
  public removed: EventEmitter<number> = new EventEmitter<number>();

  static buildItem() {
    return new FormGroup({
      title: new FormControl('', Validators.required),
      invoiceNumber: new FormControl('', Validators.required),
      grossAmount: new FormControl('', Validators.required)
    });
  }
}

When I click a button addItem() I get the following error message:

Error: formGroup expects a FormGroup instance

I create that FormGroup using the static function called buildItem as you can see. How can I fix this issue?


Solution

  • In your DeductionInvoiceItemComponent you have:

    @Input()
      public item: FormGroup;
    

    But you didn't pass it as Input from the parent component. add it:

    <app-deduction-invoice-item
              *ngFor="let item of deductionForm.get('items')?.controls; let i=index"
              [index]="i"
              [item]='item' // <-- HERE
              (removed)="deductionForm.get('items').removeAt($event)">
    </app-deduction-invoice-item>