Home > Software design >  AbstractControl<any> is missing the following properties from type FormGroup<any>: contr
AbstractControl<any> is missing the following properties from type FormGroup<any>: contr

Time:12-14

I'm working on a reactive nested form by following this YT video - enter image description here

Here are my files.

home.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormArray } from '@angular/forms';
import { MrgformComponent } from '../mrgform/mrgform.component';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  constructor() { }

  MRGForm: FormGroup = new FormGroup({
    data: new FormArray([])
  });

  ngOnInit(): void {
    this.generateMRGForm();
  }

  generateMRGForm(): void {
    this.MRGForm = new FormGroup({
      data: new FormArray([
        MrgformComponent.addMGRRowItem()
      ])
    })
  }

  submitMRGForm(): void {
    console.log(this.MRGForm.value)
  }

  get dataArray(): FormArray {
    return this.MRGForm?.get('data') as FormArray;
  }

  addRow(): void { }

  removeRow(): void { }
}

home.component.html

<div >
    <div
        >
        <div ></div>
        <div ></div>
        <div ></div>
        <div ></div>

        <div>
            <button type="button" (click)="addRow()"
                >Add</button>
        </div>
        <div>
            <button type="button" (click)="removeRow()"
                >Remove</button>
        </div>
    </div>

    <form [formGroup]="MRGForm" (ngSubmit)="submitMRGForm()">
        <app-mrgform *ngFor="let MRGChildForm of dataArray.controls" [MRGChildForm]="MRGChildForm"></app-mrgform>
        <div
            >
            <div ></div>
            <div ></div>
            <div ></div>
            <div ></div>
            <div ></div>
            <div>
                <button type="submit"
                    >Submit</button>
            </div>
        </div>
    </form>
</div>

mrgform.component.ts

import { Component, Input } from '@angular/core';
import { FormGroup, FormArray, FormControl } from '@angular/forms';


@Component({
  selector: 'app-mrgform',
  templateUrl: './mrgform.component.html',
  styleUrls: ['./mrgform.component.css']
})
export class MrgformComponent {

  propertyList: { id: string, pname: string }[] = [
    { id: '', pname: 'Select Property' },
    { id: 'PROP1', pname: 'Prop 1' },
    { id: 'PROP2', pname: 'Prop 2' },
  ];

  groupList: { id: string, gname: string }[] = [
    { id: '', gname: 'Select Group' },
    { id: 'GRP1', gname: 'Group 1' },
    { id: 'GRP2', gname: 'Group 2' }
  ];

  selectedProperty: string = '';
  selectPropertyChangeHandler(event: any) {
    this.selectedProperty = event.target.value;
    console.log('selectedProperty:', this.selectedProperty)
  }

  selectedGroup: string = '';
  selectGroupChangeHandler(event: any) {
    this.selectedGroup = event.target.value;
    console.log('selectedGroup:', this.selectedGroup)
  }

  @Input()
  MRGChildForm: FormGroup = new FormGroup({
    property: new FormControl(''),
    group: new FormControl(''),
    variableName: new FormControl(''),
    minValue: new FormControl(0),
    maxValue: new FormControl(0)
  });

  static addMGRRowItem(): FormGroup {
    return new FormGroup({
      property: new FormControl(''),
      group: new FormControl(''),
      variableName: new FormControl(''),
      minValue: new FormControl(0),
      maxValue: new FormControl(0)
    });
  }

}

mrgform.component.html

<form [formGroup]="MRGChildForm">
    <table >
        <thead >
            <tr>
                <th scope="col" >
                    Propert
                </th>
                <th scope="col" >
                    Group
                </th>
                <th scope="col" >
                    Variable Name
                </th>
                <th scope="col" >
                    Min Value
                </th>
                <th scope="col" >
                    Max Value
                </th>
            </tr>
        </thead>

        <tbody>
            <tr >
                <td >

                    <select formControlName="property" (change)="selectPropertyChangeHandler($event)">
                        <option *ngFor="let property of propertyList; index as i" value="{{property.id}}">
                            {{property.pname}}
                        </option>
                    </select>

                </td>
                <td >
                    <select formControlName="group" (change)="selectGroupChangeHandler($event)">
                        <option *ngFor="let group of groupList; index as i" value="{{group.id}}">
                            {{group.gname}}
                        </option>
                    </select>
                </td>
                <td >
                    <input formControlName="variableName" type="text" id="variable-name"
                        >
                </td>
                <td >
                    <input formControlName="minValue" type="text" id="min-input"
                        >
                </td>
                <td >
                    <input formControlName="maxValue" type="text" id="max-input"
                        >
                </td>
            </tr>
        </tbody>
    </table>
</form>

I googled & tried different things to fix this. But, I think I'm missing something. Need some helping hand.

CodePudding user response:

Solution 1

Either you can use the $any() type cast function to disable type checking.

<app-mrgform 
  *ngFor="let MRGChildForm of dataArray.controls" 
  [MRGChildForm]="$any(MRGChildForm)"
></app-mrgform>

Solution 2

Implement a function to cast AbstractControl to FormGroup.

childFormToFormGroup(form: AbstractControl): FormGroup {
  return form as FormGroup;
}
<app-mrgform
  *ngFor="let MRGChildForm of dataArray.controls"
  [MRGChildForm]="childFormToFormGroup(MRGChildForm)"
></app-mrgform>

Demo @ StackBlitz

  • Related