Angular (4): Пользовательский валидатор в форме, управляемой шаблоном, показывает текущее значение поля позади

Я не могу понять, почему мой пользовательский валидатор на один шаг отстает от значения поля. Пример: мое поле ввода имеет значение 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>

person Deniss M.    schedule 09.09.2017    source источник


Ответы (1)


Наконец удалось найти решение! Я решил пойти с 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>

Важными частями здесь являются сама директива и входящие параметры, которые можно изменить по своему вкусу.

person Deniss M.    schedule 10.09.2017