📌  相关文章
📜  mat-form-field 必须包含一个 MatFormFieldControl - TypeScript (1)

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

mat-form-field 必须包含一个 MatFormFieldControl - TypeScript

在使用 Angular Material 表单时,mat-form-field 是一个常见的组件,用于包装输入控件。但是,它不能直接包装常规的 HTML 输入控件。因此,需要使用 MatFormFieldControl 接口来定义自己的控件类型,并将其直接或间接地使用在 mat-form-field 组件内。以下是一个简单的示例:

import { Component } from '@angular/core';
import { FormControl, NgControl, NgForm } from '@angular/forms';
import { MatFormFieldControl } from '@angular/material/form-field';
import { Subject } from 'rxjs';

@Component({
  selector: 'custom-input',
  templateUrl: './custom-input.component.html',
  styleUrls: ['./custom-input.component.css'],
  providers: [{ provide: MatFormFieldControl, useExisting: CustomInputComponent }],
  // 将自定义的输入控件注册为 MatFormFieldControl
})
export class CustomInputComponent implements MatFormFieldControl<string> {

  static nextId = 0;

  stateChanges = new Subject<void>();
  focused = false;
  errorState = false;
  controlType = 'custom-input';
  id = `custom-input-${CustomInputComponent.nextId++}`;
  onChange = (_: any) => {};
  onTouched = () => {};
  value: string;

  constructor(private ngControl: NgControl) {
    if (this.ngControl != null) {
      this.ngControl.valueAccessor = this;
    }
  }

  get empty() {
    return !this.value;
  }

  get shouldLabelFloat() {
    return this.focused || !this.empty;
  }

  get placeholder() {
    return 'Enter text';
  }

  get required() {
    return false;
  }

  setDescribedByIds(ids: string[]): void {}

  onContainerClick(event: MouseEvent): void {
    this.focused = true;
    this.onTouched();
  }

  writeValue(value: string): void {
    this.value = value;
    this.onChange(value);
    this.stateChanges.next();
  }

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

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

  setDisabledState?(isDisabled: boolean): void {
    this.focused = false;
    this.errorState = false;
  }

  ngOnDestroy() {
    this.stateChanges.complete();
  }

}

在上述示例中,CustomInputComponent 实现了 MatFormFieldControl 接口,并将自身注册为一个提供者,实现方式与 Angular Material 的默认实现类似。接口中定义了一些必须实现的属性和方法,包括状态变化的 Subject,是否焦点状态,是否有错误状态,控件类型,控件 ID,变更回调函数等等。需要注意的是,该接口是一个泛型接口,支持根据自己的数据模型定义相应的泛型参数。

在定义好自定义控件后,可以将其放入 mat-form-field 作为其子节点,或者将其放到间接子节点里,如下所示:

<mat-form-field>
  <custom-input placeholder="Enter your text"></custom-input>
</mat-form-field>

这样就能够自定义输入控件,使其与 Angular Material 表单更好地配合使用了。

总之,使用 mat-form-field 进行表单构建时,必须确保其包含一个实现了 MatFormFieldControl 接口的控件,以便能够和输入框产生关联。