📌  相关文章
📜  无法绑定到“formControl”,因为它不是“输入”的已知属性. - 打字稿(1)

📅  最后修改于: 2023-12-03 14:55:07.377000             🧑  作者: Mango

无法绑定到“formControl”,因为它不是“input”的已知属性 - 打字稿

在使用Angular编写代码时,你可能会遇到如下错误:无法绑定到“formControl”,因为它不是“input”的已知属性。这是因为Angular表单控件只能绑定到标准的input、select、textarea等标签。如果你想绑定到自定义标签上,可以使用自定义表单控件来解决这个问题。

自定义表单控件

自定义表单控件是指你可以创建一个新的表单控件,并在它上面绑定表单验证器等属性。在Angular中,一个自定义表单控件由两部分组成:控件实现和控件指令。

控件实现

控件实现决定了自定义表单控件如何工作。你需要实现ControlValueAccessor接口,并提供registerOnChange和writeValue方法来将控件的值与模型中的值进行同步。代码示例如下:

import { Component, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

@Component({
  selector: 'custom-input',
  template: `
    <div class="input-wrapper">
      <input type="text" (keyup)="onChange($event.target.value)">
    </div>
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true
    }
  ]
})
export class CustomInputComponent implements ControlValueAccessor {
  public value: any;

  public onChange: (value: any) => void = () => {};

  public onTouched: () => void = () => {};

  public writeValue(value: any): void {
    this.value = value;
  }

  public registerOnChange(fn: (value: any) => void): void {
    this.onChange = fn;
  }

  public registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }
}

在上面的代码中,我们定义了一个CustomInputComponent组件,它包含了一个文本框和一个实现ControlValueAccessor接口的类。我们还提供了一个NG_VALUE_ACCESSOR的提供商,它将CustomInputComponent注册为一个可用的自定义表单控件。

控件指令

控件指令使你可以在组件中使用自定义表单控件,它将实例化你的控件并将其注册到表单中。控件指令还可以用来绑定表单验证器、设置默认值等操作。控件指令示例如下:

import { Directive, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { CustomInputComponent } from './custom-input.component';

@Directive({
  selector: '[customInput]',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputDirective),
      multi: true
    }
  ]
})
export class CustomInputDirective implements ControlValueAccessor {
  public value: any;

  constructor(private customInputComponent: CustomInputComponent) {}

  public onChange: (value: any) => void = () => {};

  public onTouched: () => void = () => {};

  public writeValue(value: any): void {
    this.customInputComponent.writeValue(value);
  }

  public registerOnChange(fn: (value: any) => void): void {
    this.onChange = fn;
    this.customInputComponent.registerOnChange(fn);
  }

  public registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
    this.customInputComponent.registerOnTouched(fn);
  }
}

在上面的代码中,我们定义了一个CustomInputDirective指令,它使用forwardRef来获取CustomInputComponent的实例并将其注册为一个表单控件。我们还实现了ControlValueAccessor接口,以便可以将该指令绑定到表单中。

使用自定义表单控件

在使用自定义表单控件时,你只需要将控件包装在一个form标签中,并将其绑定到FormControl即可。代码示例如下:

<form [formGroup]="myForm">
  <custom-input [formControl]="myControl"></custom-input>
</form>

在上面的代码中,我们将自定义表单控件包装在一个form标签中,并将它绑定到了myControl FormControl上。这里的formGroup和FormControl是Angular中表单的核心概念,如果你还不了解的话,可以查看一下官方文档。

总结

自定义表单控件是Angular中非常强大的一个功能,它允许你扩展表单控件的功能,提升用户体验。虽然它的实现可能需要一些学习成本,但一旦掌握了,你将可以使用它来实现各种自定义表单控件,极大地提升了你的开发效率。