Angular 使用 ReactiveForms 验证 ControlValueAccessor

问题描述 投票:0回答:1

我使用 ControlValueAccessor 在 Angular 中创建自定义输入。我发现 FormControls 的验证停止工作了。

这是我在 Stackblitz 上制作的一个简单示例。

@Component({
  selector: 'app-text-field',
  templateUrl: './text-field.component.html',
  standalone: true,
  imports: [CommonModule, FormsModule],
})
export class TextFieldComponent implements ControlValueAccessor, OnInit {
  protected control = inject(NgControl); // control should be injected

  onChange(value: string) {}
  onTouch() {}

  value = '';

  ngOnInit(): void {
    this.control.valueAccessor = this;
  }

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

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

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

我无法提供

NG_VALIDATORS
,因为它会创建循环依赖关系,并且找不到任何在 Angular 16+ 中仍然可用或可以被视为最佳实践的代码。

那么支持验证的最佳方式是什么?

编辑1:

这也是输入的使用方式:

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule, TextFieldComponent],
  template: `
    <form [formGroup]="form">
      <app-text-field formControlName="a" />
    </form>
    <p>{{ form.errors }}</p>
  `,
})
export class App {
  form = new FormGroup({
    a: new FormControl<string>('', {
      validators: [
        Validators.required,
        Validators.maxLength(8),
        Validators.minLength(2),
      ],
    }),
  });

  constructor() {
    this.form.valueChanges.subscribe((val) =>
      console.log(val, this.form.errors)
    );
  }
}
javascript html angular angular-forms
1个回答
0
投票

您可以使用

forwardRef
来打破循环依赖。

@Component({
  standalone: true,
  imports: [CommonModule, FormsModule, forwardRef(() => NG_VALIDATORS)],
  selector: 'app-text-field',
  templateUrl: './text-field.component.html',
})
export class TextFieldComponent {}

参见 https://angular.io/api/core/forwardRef

© www.soinside.com 2019 - 2024. All rights reserved.