Angular (4): Custom Validator in a Template-Driven form 显示后面字段的当前值

Angular (4): Custom Validator in a Template-Driven form shows the current value of the field behind

我似乎无法弄清楚为什么我的自定义验证器比字段值落后一步。示例:我的输入字段的值是 123,一一输入。但是我的验证器的值为 12。

我无法正确比较两个字段之间的值。 这是指令中的验证器:

@Directive({
  selector: '[validateEqual][formControlName],[validateEqual][formControl],[validateEqual][ngModel]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => PasswordValidationDirective),
      multi: true
    }
  ]
})
export class PasswordValidationDirective implements Validator {
  @Input('first') first: string;
  @Input('second') second: string;

  constructor() {
  }

  public validate(ac: AbstractControl): { [key: string]: any } {
    console.log(ac.root);
    return null;
  }
}

这是字段的html:

<md-input-container class="full-width">
  <input mdInput
         type="password"
         required
         ngModel name="passwordConfirmation"
         #passwordConfirmation="ngModel"
         minlength="6"
         maxlength="30"
         pattern="(?=^.{6,30}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$"
         validateEqual
         first="password"
         second="passwordConfirmation"
         placeholder="{{'PASSWORD_RECOVERY.PASSWORD_CONFIRMATION' | translate}}">
  <md-error *ngIf="passwordConfirmation.touched && passwordConfirmation.invalid">
    <span *ngIf="passwordConfirmation.errors.required">
      {{'PASSWORD_RECOVERY.FIELD_REQUIRED' | translate}}
    </span>
    <span *ngIf="passwordConfirmation.errors.minlength || passwordConfirmation.errors.maxlength">
      {{'PASSWORD_RECOVERY.PASSWORD_LENGTH' | translate}}
    </span>
    <span *ngIf="passwordConfirmation.errors.pattern" class="p-md-error-multiline-div">
      {{'PASSWORD_RECOVERY.FOR_A_SECURE_PASSWORD' | translate}}
    </span>
  </md-error>
</md-input-container>

终于找到解决办法了!我决定选择 NgModelGroup。这是指令:

@Directive({
  selector: '[validateEqual][ngModelGroup]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => PasswordValidationDirective),
      multi: true
    }
  ]
})
export class PasswordValidationDirective implements Validator {
  @Input('password') public password: string;
  @Input('confirmation') public confirmation: string;

  public validate(fg: FormGroup): { [key: string]: any } {
    const fieldOne = fg.value[this.password];
    const fieldTwo = fg.value[this.confirmation];

    if (!fieldOne || !fieldTwo || fieldOne === fieldTwo ) {
      return null;
    }

    return {valueEquals: false};

  }
}

这里是 HTML:

<div ngModelGroup="passwordGroup"
     #passwordGroup="ngModelGroup"
     validateEqual
     password="password"
     confirmation="passwordConfirmation">
  <div class="row">
    <div class="col-xs-6">
      <md-input-container class="full-width">
        <input mdInput
               type="password"
               required
               ngModel name="password"
               #password="ngModel"
               placeholder="{{'SIGNUP.PASSWORD' | translate}}">
      </md-input-container>
    </div>
    <div class="col-xs-6">
      <md-input-container class="full-width">
        <input mdInput
               type="password"
               required
               ngModel name="passwordConfirmation"
               #passwordConfirmation="ngModel"
               placeholder="{{'SIGNUP.RETYPE_PASSWORD' | translate}}">
      </md-input-container>
    </div>
  </div>
  <div class="row">
    <div class="col-xs-12">
      <md-error *ngIf="passwordGroup.errors">
        <span class="p-text-small-error">{{'SIGNUP.MATCH' | translate}}</span>
      </md-error>
    </div>
  </div>
</div>

这里重要的部分是指令本身和传入的参数,可以根据自己的喜好进行修改。