Angular 2事件监听器条件竞赛

时间:2017-11-03 07:32:26

标签: angular javascript-events angular2-forms angular2-directives race-condition

我有一个实现

的指令appValidateOnChange
@HostListener('focus') onFocus() {
    this.validators = this.formControl.control.validator;
    this.asyncValidators = this.formControl.control.asyncValidator;
    this.formControl.control.clearAsyncValidators();
    this.formControl.control.clearValidators();
}
@HostListener('change') onChange() {
    this.formControl.control.setAsyncValidators(this.asyncValidators);
    this.formControl.control.setValidators(this.validators);
    this.formControl.control.updateValueAndValidity();
}

目标是在验证之前等待用户完成输入。我简单地称之为

<input
        type="text"
        class="form-control"
        id="field"
        name="field"
        [ngModel]="fieldValue"
        #fieldName="ngModel"
        required
        minlength="8"
        (change)="updateField(fieldName)"
        appValidateOnChange>

updateField函数中

if(!field.valid)
    return false;

问题是,两个change事件之间存在竞争条件。

有时一切都按预期工作,因为指令的事件首先触发,而其他一些时候验证被忽略,因为指令的事件触发第二。

我该如何解决?我想避免setTimeout

4 个答案:

答案 0 :(得分:2)

如果您已升级到Angular 5,则添加了一项新功能,仅在blur上进行验证,例如:

<input name="firstName" ngModel [ngModelOptions]="{updateOn: 'blur'}">

我引用了标题下的文档外观 Angular Forms添加updateOn模糊/提交

https://blog.angular.io/version-5-0-0-of-angular-now-available-37e414935ced

答案 1 :(得分:1)

我不会在控件具有焦点时显示验证结果,并且在默认验证发生时完全忽略。

使用焦点和模糊事件设置/清除标记并在设置标记时隐藏验证警告(使用*ngIf[hidden]="myFlag"

答案 2 :(得分:1)

我认为如果使用ngModelChange而不是更改,则使用ngModel时, 然后指令总是先被激活:
HTML

<input myDirective
        type="text"
        class="form-control"
        id="field"
        name="field"
        [ngModel]="fieldValue"
        #fieldName="ngModel"
        required
        minlength="8"
        (ngModelChange)="updateField(fieldName)"
        appValidateOnChange>

<强>指令

@HostListener('ngModelChange') onChange() {
  console.log("onChange fired")
}

DEMO

答案 3 :(得分:0)

我不确定这是否可以通过模板驱动的形式实现。有了反应,你可以这样做:

模板:

<input formControlName="myName" (blur)="update('myName')">

成分:

update(name: string) {
    this.form.controls[name].updateValueAndValidity();
}