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

📅  最后修改于: 2023-12-03 15:10:26.791000             🧑  作者: Mango

无法绑定到“ngModel”,因为它不是“输入”的已知属性

当开发 Angular 应用时,我们常常会使用 ngModel 指令来实现数据双向绑定。然而,有时候会出现以下错误信息:

无法绑定到“ngModel”,因为它不是“输入”的已知属性。

这是因为,ngModel 不是一个“输入属性”。那么什么是“输入属性”呢?

在 Angular 中,指令通过“输入属性”与组件进行交互,也可以把它们看作在组件和指令之间传递数据的门户。例如,通过 @Input 装饰器可以将属性绑定到组件:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: `<h1>Hello {{name}}!</h1>`
})
export class MyComponent {
  @Input() name: string;
}

在此示例中,@Input() 装饰器将 name 属性声明为组件的输入属性。这意味着该属性的值可以来自组件的父组件,通过属性绑定语法将其传递给组件:

<app-my-component [name]="'John'"></app-my-component>

然而,ngModel 并非组件的输入属性。相反,它是一个指令,用于实现双向绑定。这就是为什么在某些情况下,Angular 编译器会报告无法将 ngModel 绑定到组件的原因。

要解决此问题,可以在组件的构造函数中导入 ControlValueAccessor:

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

@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MyComponent),
      multi: true
    }
  ]
})
export class MyComponent implements OnInit, ControlValueAccessor {

  value: any;

  constructor() { }

  ngOnInit() {
  }

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

  registerOnChange(fn: any) {
    this.onChange = fn;
  }

  registerOnTouched(fn: any) {
    this.onTouched = fn;
  }

  onChange(value: any) {}

  onTouched() {}

}

在此示例中,我们将实现 ControlValueAccessor 接口的 MyComponent 声明为组件提供程序的一个提供。该接口有四个方法:

  • writeValue: 当组件从模型更新值时调用此方法
  • registerOnChange: 当组件的值更改时,此方法将更改通知模型。
  • registerOnTouched: 该方法在组件失去焦点时被调用,并用于通知模型,以便做出必要的更改。
  • onChange: 当组件的值更改时,此方法将被调用,以更新组件的值。

要将组件与 ngModel 一起使用,可以使用 [(ngModel)] 语法:

<app-my-component [(ngModel)]="myValue"></app-my-component>

请注意,如果要使用 [(ngModel)],则必须同时导入 FormsModule 和 ReactiveFormsModule 模块。

总结

以上是解决“无法绑定到‘ngModel’,因为它不是‘输入’的已知属性”的方法。在某些情况下,将 ControlValueAccessor 接口实现为组件的提供程序可用于解决此问题。请记住,ngModel 并非组件的输入属性,因此无法像其他组件输入属性那样进行绑定。