实现 ControlValueAccessor 和 Validator 的 MatFormFieldControl 创建循环依赖

Mar*_*tin 9 typescript angular-material angular-components angular angular5

我正在尝试通过实现 MatFormFieldControl、ControlValueAccessor 和 Validator 接口来创建自定义表单控件。

但是,当我提供NG_VALUE_ACCESSORNG_VALIDATORS...

@Component({
  selector: 'fe-phone-number-input',
  templateUrl: './phone-number-input.component.html',
  styleUrls: ['./phone-number-input.component.scss'],
  providers: [
    {
      provide: MatFormFieldControl,
      useExisting: forwardRef(() => PhoneNumberInputComponent)
    },
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => PhoneNumberInputComponent),
      multi: true,
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => PhoneNumberInputComponent),
      multi: true
    }
  ]
})
export class PhoneNumberInputComponent implements MatFormFieldControl<string>,
  ControlValueAccessor, Validator, OnDestroy {
  ...
}
Run Code Online (Sandbox Code Playgroud)

创建循环依赖:

未捕获的错误:模板解析错误:无法实例化循环依赖!控件

这有效:

@Component({
  selector: 'fe-phone-number-input',
  templateUrl: './phone-number-input.component.html',
  styleUrls: ['./phone-number-input.component.scss'],
  providers: [
    {
      provide: MatFormFieldControl,
      useExisting: forwardRef(() => PhoneNumberInputComponent)
    }
  ]
})
export class PhoneNumberInputComponent implements MatFormFieldControl<string>,
  ControlValueAccessor, Validator, OnDestroy {
  ...
  constructor(@Optional() @Self() public ngControl: NgControl) {
    if (this.ngControl) {
      this.ngControl.valueAccessor = this;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但我仍然无法弄清楚如何进行验证工作。提供NG_VALIDATORS会产生循环依赖。如果不提供它,validate方法就不会被调用。

我正在使用@angular/material 5.0.4。

Mar*_*tin 4

为了摆脱循环依赖,我Validator从组件中删除了接口,而是直接提供验证器函数。

export function phoneNumberValidator(control: AbstractControl) {
  ...
}

@Component({
  selector: 'fe-phone-number-input',
  templateUrl: './phone-number-input.component.html',
  styleUrls: ['./phone-number-input.component.scss'],
  providers: [
    {
      provide: MatFormFieldControl,
      useExisting: forwardRef(() => PhoneNumberInputComponent)
    },
    {
      provide: NG_VALIDATORS,
      useValue: phoneNumberValidator,
      multi: true
    }
  ]
})
export class PhoneNumberInputComponent implements MatFormFieldControl<string>,
  ControlValueAccessor, OnDestroy {
  ...
  constructor(@Optional() @Self() public ngControl: NgControl) {
    if (this.ngControl) {
      this.ngControl.valueAccessor = this;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 您将如何从验证器函数访问输入组件实例?有可能吗? (8认同)