Why am I getting this error?
The following code works in another application
<input class="form-control form-control-sm" type="number" min="0"
[formControl]='invoiceForm.get("quantity")'>
in this new application it works too but still complaining in the terminal
Type 'AbstractControl' is not assignable to type 'FormControl'.
You can try
<input class="form-control form-control-sm" type="number" min="0"
[formControl]='invoiceForm.controls.quantity'>
or my personal favorite way of handlingforms
<div [formGroup]="inviceForm"> <!-- any tag that wraps all of your controls -->
<!-- some input before (anything)-->
<input class="form-control form-control-sm" type="number" min="0"
formControlName='quantity'>
<!-- some inputs after (anything)-->
</div>
From this official documentation and according to the FormControl definition, we can see that FormControl inherits from AbstractControl. And since FormGroup.controls and FormGroup.get("key") both return an AbstractControl, I had to create a function to cast from Parent to Child class.
toControl(absCtrl: AbstractControl): FormControl {
const ctrl = absCtrl as FormControl;
// if(!ctrl) throw;
return ctrl;
}
and the template
<input class="form-control form-control-sm" type="number" min="0"
[formControl]='toControl(invoiceForm.get("quantity"))'>
PS: I could not use FormControlName because I have many form groups and sub groups/arrays. That's I had to use the banana in box directive, because it's value is strongly typed
I was able to get around this issue by giving the template direct access to the FormControl as well as adding it to the form in initForm().
.ts
form: FormGroup = new FormGroup({});
quantity: FormControl = new FormControl(Quantity.MIN, [
Validators.min(Quantity.MIN),
Validators.max(Quantity.MAX),
]);
ngOnInit(): void {
this.initForm();
}
initForm(): void {
this.form.addControl('quantity', this.quantity);
}
.html (In my case I am passing the FormControl quantity to a custom component that takes a FormControl Input() named "control".)
<form [formGroup]="form" (ngSubmit)="submit()">
<app-select-quantity [control]="quantity"></app-select-quantity>
<div>
<button
mat-flat-button
type="submit"
color="primary"
[disabled]="!form.valid"
>
Submit
</button>
</div>
</form>
This issue might come from tsconfig.json if you're using Angular 9 or above
"angularCompilerOptions": {
...
"strictTemplates": true <-- causing "Type 'AbstractControl' is not assignable to type 'FormControl'"
}
First Option
by setting "strictTemplates": false might temporary "solve" the problem
Second Option
by convert the AbstractControl to FormControl through template, so your .ts file should have
convertToFormControl(absCtrl: AbstractControl | null): FormControl {
const ctrl = absCtrl as FormControl;
return ctrl;
}
and your html
<input
type="text"
[formControl]="convertToFormControl(invoiceForm.get("quantity"))"
/>
If there are different versions or no 'type' conversion matches you can use 'any' as a temporary solution. For e.g
From :
event: FormControl
To :
event: any
<input type="name" placeholder="Name" class="form-control" [formControl]="$any(cardForm).controls.name" />
Here $any function would disable type checking.