网站搜索

angular - 在 @Input 变化时触发自定义表单控件验证


我有一个带有一个输入的简单自定义表单控件:

const NGX_HELLO_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => HelloComponent),
    multi: true
};

const NGX_HELLO_VALIDATORS = {
    provide: NG_VALIDATORS,
    useExisting: forwardRef(() => HelloComponent),
    multi: true
};

@Component({
    selector: 'hello',
    template: `<p>Value in custom form control: {{value}}</p>`,
    providers: [NGX_HELLO_VALUE_ACCESSOR, NGX_HELLO_VALIDATORS]
})
export class HelloComponent implements OnChanges, ControlValueAccessor, Validator  {

    @Input() maxLength: number;

    value: string;
    onChangeCb: (_: any) => void = () => { };
    onTouchedCb: () => void = () => { };

    ngOnChanges(changes: SimpleChanges): void {
        //trigger validation
    }

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

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

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

    validate(control: FormControl): ValidationErrors {
        if(this.value && this.value.length > this.maxLength) {
            return {
                tooLong: this.maxLength
            };
        }
        return null;
    }
}

这工作得很好。每当值改变时,Angular 会调用 validate,并且控件会被验证。问题是,当 @Input maxLength 改变时,如何运行验证?

我创建了一个 StackBlitz 示例来尝试操作。

答案#1

 ngOnChanges(changes: SimpleChanges): void {
    //trigger validation
    this.onChangeCb(this.value);
  }

行得通,似乎 Angular 在值变化时会重新运行验证。

分叉的 stackblitz

答案#2

对于这种情况,Validator 接口提供了一个通过 registerOnValidatorChange 的回调。