模板错误类型“AbstractControl”无法分配给类型“FormControl”

Bel*_*ash 45 angular angular-reactive-forms

为什么我会收到此错误?

以下代码在另一个应用程序中有效

          <input class="form-control form-control-sm" type="number" min="0"
            [formControl]='invoiceForm.get("quantity")'>
Run Code Online (Sandbox Code Playgroud)

在这个新应用程序中它也可以工作,但仍然在终端中抱怨

  Type 'AbstractControl' is not assignable to type 'FormControl'.
Run Code Online (Sandbox Code Playgroud)

小智 41

<input type="password" placeholder="Confirm Password" class="form-control" [formControl]="$any(myForm).controls['confirmpassword']"/> 
Run Code Online (Sandbox Code Playgroud)

使用$any函数禁用类型检查。我用这个解决了我的错误。

  • 请参阅下面的@Avetik 评论,了解更清洁的管道解决方案。/sf/answers/5076243721/ (2认同)

Ave*_*tik 34

如果其他人仍然遇到这个问题,我会分享我的解决方案,该解决方案与Bellash所描述的几乎相同,但性能更好。对于这个例子:

<input class="form-control form-control-sm" type="number" min="0"
        [formControl]='invoiceForm.get("quantity")' | formControl>
Run Code Online (Sandbox Code Playgroud)

我们只需要创建并使用管道,它将返回正确类型的值

@Pipe({
    name: 'formControl',
})
export class FormControlPipe implements PipeTransform {
    transform(value: AbstractControl): FormControl<typeof value['value']> {
        return value as FormControl<typeof value['value']>;
    }
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您将获得更好的性能,因为仅当提供的表单发生更改时才会调用管道转换函数。

通常,在模板中使用函数是不好的做法,因为每个生命周期更改都会调用此函数,并且在较大的项目上会产生很大的性能问题。最好的方法是使用管道(通常正是为了此类目的而开发的),仅在渲染时转换某些值(仅当某些值需要更改时)。希望这会对某人有所帮助)

  • 比其他人更好的解决方案。但我必须在 Angular 13 中删除泛型 &lt;typeof value['value']&gt; 。 (2认同)

jdc*_*czw 13

tsconfig.json如果您使用 Angular 9 或更高版本,则可能会出现此问题

"angularCompilerOptions": {
    ...
    "strictTemplates": true <-- causing "Type 'AbstractControl' is not assignable to type 'FormControl'"
  }
Run Code Online (Sandbox Code Playgroud)

第一个选项

通过设置"strictTemplates": false可能会暂时“解决”问题

第二个选项

通过将其转换AbstractControlFormControl通过模板,因此您的.ts文件应该具有

convertToFormControl(absCtrl: AbstractControl | null): FormControl {
    const ctrl = absCtrl as FormControl;
    return ctrl;
  }
Run Code Online (Sandbox Code Playgroud)

和你的html

<input
    type="text"
    [formControl]="convertToFormControl(invoiceForm.get("quantity"))"
  />
Run Code Online (Sandbox Code Playgroud)


Bel*_*ash 9

从这个官方文档中,根据FormControl的定义,我们可以看到FormControl继承自AbstractControl。由于FormGroup.controlsFormGroup.get("key")都返回一个AbstractControl,我必须创建一个函数来从 Parent 类转换为 Child 类。

toControl(absCtrl: AbstractControl): FormControl {
    const ctrl = absCtrl as FormControl;
    // if(!ctrl) throw;
    return ctrl;
}
Run Code Online (Sandbox Code Playgroud)

和模板

 <input class="form-control form-control-sm" type="number" min="0"
        [formControl]='toControl(invoiceForm.get("quantity"))'>
Run Code Online (Sandbox Code Playgroud)

PS:我无法使用,FormControlName因为我有很多表单组和子组/数组。那就是我必须使用banana in box指令,因为它的值是强类型的

编辑 2022:另请考虑下面的 @Avetik 答案,将此函数转换为管道以获得更好的性能


Ant*_*sss -1

你可以试试

<input class="form-control form-control-sm" type="number" min="0"
            [formControl]='invoiceForm.controls.quantity'>
Run Code Online (Sandbox Code Playgroud)

或者我个人最喜欢的处理表单的方式

<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>
Run Code Online (Sandbox Code Playgroud)