Angular 使用 ControlValueAccessor 时的表单控件验证

Angular form control validation when using ControlValueAccessor

在父组件中我定义了表单。

  cartForm = new FormGroup({
    company: new FormControl('', [Validators.required]),
    costCenter: new FormGroup({
      account: new FormControl('', [Validators.required]),
      activity: new FormControl('', [Validators.required, Validators.maxLength(5), Validators.minLength(5)]),
      project: new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(10)]),
    })
  });

然后在子组件中使用 formControl project。在此组件中,我需要自定义验证,只需添加

即可实现
  validate(control: AbstractControl): ValidationErrors | null {
    // To my validation here
  }

除了在父组件中指定的 Validators 被覆盖外,这有效。

第二种方法是创建一个自定义验证器class..但是我无法从组件中获取@Input..?

更新:这是组件

@Component({
  selector: 'ssp-project',
  templateUrl: './project.component.html',
  styleUrls: ['./project.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProjectComponent implements ControlValueAccessor, OnInit {

  @Input('companyNumber') set companyNumber(companyNumber: string) {
    this._companyNumber = companyNumber;
  }
  private _companyNumber: string;

  constructor(
    @Optional() @Self() public ngControl: NgControl,
  ) {
    if (this.ngControl != null) {
      // Setting the value accessor directly (instead of using the providers) to avoid running into a circular import.
      this.ngControl.valueAccessor = this;
    }
  }

  onTouched = (_value?: any) => { };
  onChanged = (_value?: any) => { };

  writeValue(val: string): void {
    if (val) {
      this.ngControl.control?.setValue(val);
    }

  }

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

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

  registerOnValidatorChange(fn: any): void {
    this.onChanged = fn;
  }

  ngOnInit() {
    // this.ngControl.control.setValidators([this.validate.bind(this)]);
    this.ngControl.control.setValidators(this.ngControl.control.validator ? [this.ngControl.control.validator, this.validate] : this.validate);
    this.ngControl.control.updateValueAndValidity();
  }

  validate(control: AbstractControl): ValidationErrors | null {

    if (this._companyNumber && control.value) {
      return this._costCenterService
        .validateProject(control.value, this._companyNumber)
        .pipe(
          debounceTime(3000),
          map(projectIsValid => {
            return { invalid: !projectIsValid };
          })
        ).subscribe();

    }
  }
}

您可以使用 FormControl

validator 属性 将验证器添加到现有验证器列表中
control.setValidators(control.validator ? [ control.validator, this.validate ] : this.validate);

编辑:由于在问题中添加了代码,焦点已转移到异步验证器上。例如:

control.setAsyncValidators(
  control.asyncValidator
    ? [control.asyncValidator, this.asyncValidator]
    : this.asyncValidator
);

// definition of asyncValidator
asyncValidator(ctrl: AbstractControl): Observable<ValidationErrors | null> {
  // Whatever your validation does asynchronously
  return of(null);
}