Angular error TS2739: Type 'AbstractControl' is missing the following properties from type 'FormControl'

Viewed 2453

I'm trying to add a formArray to my form, following this article. The error I'm getting is pasted at the bottom and seems to be an issue with [formControl]="devices.controls[i]" on the input. The error is preventing me from serving my app but I can't figure out what is wrong with it.

HTML

<div formArrayName="devices">
    <h3>Devices</h3>
    <button (click)="addDevice()">Add Device</button>

    <div *ngFor="let control of devices.controls; index as i">
        <label>
            Device:
            <input type="text" [formControl]="devices.controls[i]">
        </label>
    </div>
</div>

TS

terminalNameInput = new FormControl();
devices = new FormArray([]);

addTerminalGroup = new FormGroup({
    terminalNameInput : this.terminalNameInput,
    devices : this.devices,
});

addDevice() {
    this.devices.push(new FormControl(''));
}

FULL ERROR

error TS2739: Type 'AbstractControl' is missing the following properties from type 'FormControl': registerOnChange, registerOnDisabledChange, _applyFormState

3 Answers

You will need to add stronger typing to your component model. You can cast your AbstractControl as FormControl and create a reference to devices.controls Then you can create a method that gets a FormControl rather than AbstractControl

You can do that by changing your component.ts as follows


addTerminalGroup: FormGroup;
get terminalNameInput(): FormControl { this.addTerminalGroup.controls.terminalNameInput as FormControl }
get devices(): FormArray { this.addTerminalGroup.controls.devices as FormArray }

constructor(private formBuilder:FormBuilder){
    this.addTerminalGroup = this.formBuilder.group({
        terminalNameInput : new FormControl('', []),
        devices : new FormArray(),
    });
}

addDevice() {
    this.devices.push(new FormControl(''));
}

// Used to get a strongly typed FormControl
getDeviceByIndex(index: number): FormControl {
    return this.devices.at(index) as FormControl;
}

Then in your component.html you can replace

<input type="text" [formControl]="devices.controls[i]">

with the following

<input type="text" [formControl]="getDeviceByIndex(i)">

IDK how to properly fix this error (I bumped into your question by researching this problem I myself was having), here is how I got rid of it:

Remove or set to false the strictTemplates option for angularCompilerOptions in the tsconfig.json file:

...
,
  "angularCompilerOptions": {
    "strictTemplates": false
  }

As it's not a good solution for disabling the whole string templates, as it's an usefull feature for bug tracing for me. You can just use a any cast for this formControl input [formControl]="$any(formControl)" or [formControl]="$any(devices.controls[i])" in your case.

The error is caused because of the abstract FieldType in my case.

readonly formControl: import("@angular/forms").AbstractControl;

[Edit] This should be only a temporary workaround, till the strict template checking works as expected.

Related