为什么我会收到此错误?
以下代码适用于另一个应用程序
<input class="form-control form-control-sm" type="number" min="0"
[formControl]='invoiceForm.get("quantity")'>
在这个新应用程序中它也可以工作,但仍然在终端中抱怨
Type 'AbstractControl' is not assignable to type 'FormControl'.
<input type="password" placeholder="Confirm Password" class="form-control" [formControl]="$any(myForm).controls['confirmpassword']"/>
使用 $any 函数禁用类型检查。我用这个解决了我的错误。
如果其他人仍然遇到这个问题,我分享我的解决方案,它与Bellash描述的几乎相同,但性能更好。 对于这个例子:
<input class="form-control form-control-sm" type="number" min="0"
[formControl]='invoiceForm.get("quantity")' | formControl>
我们只需要创建并使用管道,它将返回正确类型的值
@Pipe({
name: 'formControl',
})
export class FormControlPipe implements PipeTransform {
transform(value: AbstractControl): FormControl<typeof value['value']> {
return value as FormControl<typeof value['value']>;
}
}
通过这种方式,您将获得更好的性能,因为仅当提供的表单发生更改时才会调用管道转换函数。
通常在模板中使用函数是不好的做法,因为每个生命周期更改都会调用此函数,并且在较大的项目上会产生很大的性能问题。最好的方法是使用管道(通常正是为了此类目的而开发的),仅在渲染时转换某些值(仅当某些值需要更改时)。 希望这会对某人有所帮助)
如果您使用 Angular 9 或更高版本,此问题可能来自
tsconfig.json
"angularCompilerOptions": {
...
"strictTemplates": true <-- causing "Type 'AbstractControl' is not assignable to type 'FormControl'"
}
第一个选项
通过设置
"strictTemplates": false
可能会暂时“解决”问题
第二个选项
通过模板将
AbstractControl
转换为FormControl
,所以你的.ts
文件应该有
convertToFormControl(absCtrl: AbstractControl | null): FormControl {
const ctrl = absCtrl as FormControl;
return ctrl;
}
还有你的
html
<input
type="text"
[formControl]="convertToFormControl(invoiceForm.get("quantity"))"
/>
从这个官方文档以及根据FormControl定义,我们可以看到FormControl继承自AbstractControl。由于
FormGroup.controls
和 FormGroup.get("key")
都返回 AbstractControl
,我必须创建一个函数来从 Parent 类转换为 Child 类。
toControl(absCtrl: AbstractControl): FormControl {
const ctrl = absCtrl as FormControl;
// if(!ctrl) throw;
return ctrl;
}
和模板
<input class="form-control form-control-sm" type="number" min="0"
[formControl]='toControl(invoiceForm.get("quantity"))'>
PS:我无法使用
FormControlName
,因为我有很多表单组和子组/数组。那就是我必须使用banana in box指令,因为它的值是强类型的
编辑 2022:另请考虑下面的 @Avetik 答案,将此函数转换为管道以获得更好的性能
感谢 Avetik 和 Imo 提供我列出的大部分信息。以下步骤适用于 Angular 13+:
在基础项目文件夹中创建文件 form-control.pipe.ts:
import {Pipe, PipeTransform} from '@angular/core';
import {AbstractControl, FormControl} from '@angular/forms';
@Pipe({
name: 'formControl',
})
export class FormControlPipe implements PipeTransform {
transform(value: AbstractControl): FormControl {
return value as FormControl;
}
}
在项目的 @NgModule 的声明部分中,将 FormControlPipe 添加到列表中并导入它。
在任何地方收到此 lint 警告,请添加 | FormControl(包括管道符号)
[formControl]="form.get('wordRuleForm').get('sound') | formControl"
问题解决了!
我有一个与formGroup类似的控件,所以我基于formGroup创建了一个类似的过滤器,它的使用方式如下:
[commonForm]="form.get('commonForm') | formGroup"
我可以通过让模板直接访问
FormControl
并将其添加到 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(在我的例子中,我将
FormControl
数量传递给一个自定义组件,该组件采用名为“control”的 FormControl
Input()
。)
<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>
<input type="name" placeholder="Name" class="form-control" [formControl]="$any(cardForm).controls.name" />
这里
$any
函数将禁用类型检查。
我并不是很热衷于使用解决方法(所有答案似乎都是如此),并且碰巧遇到了 Angular University 示例中使用的策略。
您可以通过将
get
属性公开给模板上的 formControlName
来轻松地将表单控件公开给表单:
<input class="form-control form-control-sm" type="number" min="0"
formControlName='quantity'> <!-- formControlName instead of [formControl] -->
在组件中:
// The get property should match the formControlName above.
get quantity() {
return this.form.controls["quantity"];
}
这个 Angular 问题与切线相关,但很有趣 - 对于自定义类型的表单:
(表单):类型化表单和泛型/继承的问题。 https://github.com/angular/angular/issues/47091
你可以试试
<input class="form-control form-control-sm" type="number" min="0"
[formControl]='invoiceForm.controls.quantity'>
或者我个人最喜欢的处理表单的方式
<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>
如果存在不同版本或没有“类型”转换匹配,您可以使用“任何”作为临时解决方案。例如
来自:
event: FormControl
致:
event: any