初始化输入时缺少asyncValidator(Angular 7.0.1)

时间:2018-10-25 18:47:42

标签: angular angular7

只需升级到Angular 7.0.1并使用formControl的asyncValidator(我将asyncValidator指令链接到我的formControl)就遇到了奇怪的行为。

在带有asyncValidator指令的输入的初始化组件上,我没有将asyncValidator链接到我的formControl,但是在验证器中触发了“ validate”函数(该函数收集了错误)!

no asyncValidator on formControl collected error but asyncValidator does not have them

在组件初始化并更改输入值(使用此formControl)之后,asyncValidator神奇地出现,并且一切正常。

asyncValidator magically appears

问题是,在从控件计算并添加到init时,init输入的错误没有显示。

在Angular 6+中,一切都很好!

查看屏幕截图。

有人遇到同样的问题吗?

2 个答案:

答案 0 :(得分:0)

我错了,Angular 6+的行为相同,但显示出验证错误。忘记提及了,我使用的是“ OnPush”策略。

在Angular 6+上:

  1. 在组件初始化时触发状态为“ Valid”的“ formControl”“ statusChanges”事件,而未链接“ asyncValidator”
  2. 在我的指令(“ asyncValidator”)中调用此“验证”功能后,该功能会收集错误
  3. 使用空输入启动组件视图时,输入具有“无效”下划线和预期错误

在Angular 7+上:

1-2。相同的行为

  1. 输入出现时没有“无效”下划线,并且在被触摸(聚焦)时,直到聚焦之前都出现错误-出现错误:\

这是我的“ asyncValidate”指令:

@Input()
public propertyName: string;

private get _businessObject(): BusinessBase {
    return this._fieldComponentBase.businessObject;
}

private _propertyChangedSubscription: Subscription;

constructor(private _fieldComponentBase: FieldComponentBase) {}

public ngOnDestroy() {
    this.unsubscribeFromPropertyChangedEvent();
}

public validate(abstractControl: FormControl): Promise<ValidationErrors> | Observable<ValidationErrors> {
    if (!this.propertyName) {
        throw new Error('Property name of business object was not provided.');
    }

    if (!this._businessObject) {
        throw new Error('Business object was not provided.');
    }

    return new Promise(resolve => {
        const errors: ValidationErrors = {};

        if (this._businessObject.shouldPristineFormControl(this.propertyName)) {
            abstractControl.markAsPristine();


     this._businessObject.removePropertyFormControlPristineStatus(this.propertyName);
        }

        if (abstractControl.dirty) {
            this.unsubscribeFromPropertyChangedEvent();

            this._propertyChangedSubscription = this._businessObject.propertyChanged
                .subscribe((propertyChangedEvent: PropertyChangedEvent) => {
                    if (propertyChangedEvent.propertyName !== this.propertyName) {
                        return;
                    }

                    this.unsubscribeFromPropertyChangedEvent();

                    this.setErrors(errors);

                    resolve(errors);
                });
        } else {
            this.setErrors(errors);

            resolve(errors);
        }
    });
}

private setErrors(errors: ValidationErrors) {
    this._businessObject.getBrokenRules(undefined, this.propertyName).forEach((brokenRule, index) => {
        errors[index] = brokenRule.message;
    });
}

private unsubscribeFromPropertyChangedEvent() {
    if (!this._propertyChangedSubscription) {
        return;
    }

    this._propertyChangedSubscription.unsubscribe();

    this._propertyChangedSubscription = undefined;
}

这是我的表单控件的“ statusChanges”侦听器:

this.formControl.statusChanges.subscribe((status: 'VALID' | 'INVALID' | 'PENDING') => {
        if (!this._formControlStatus) {
            this._formControlStatus = status;

            return;
        }

        if (status === 'PENDING' || status === 'VALID' && status === this._formControlStatus) {
            return;
        }

        this._formControlStatus = status;

        /**
         * Should update component bindings if error calculation took too long.
         */
        this.changeDetectorRef.markForCheck();
    });

答案 1 :(得分:0)

好吧,经过一些小变通后,才想到了以下解决方案:

        if (!this._formControlStatus) {
            this._formControlStatus = status;

            /**
             * Should update component bindings after small timeout on first init.
             *
             * Otherwise validation (if exists) will not be desplayed untill focusing input.
             */
            timer(1).subscribe(() => {
                this.changeDetectorRef.detectChanges();
            });

            return;
        }

如果id尚未兑现“ _formControlStatus”,则意味着第一次从控件输入的信息是init,并且在短暂延迟后评估“ detectChanges”将使用输入信息更新视图:\