Angular 2匹配表单中的密码

时间:2017-11-06 10:54:59

标签: angular angular2-forms

我知道这个问题已被其他时间以类似的形式提出,但我的情况有所不同;让我解释一下:

我有一个重置密码表单,有3个字段(旧密码,新密码,确认密码)。当然,我需要检查提交的passowrd是否与提交的确认密码相同,我想在点击提交之前执行此操作。我将表单定义如下(在component.ts中)

this.form = fb.group({
  // define your control in you form
  oldpassword: ['', Validators.required],
  password: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(10)]],
  confirmPassword: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(10)]]
}, {
  validator: PasswordValidation.MatchPassword // your validation method
});

export class PasswordValidation {

static MatchPassword(AC: AbstractControl) {
    const password = AC.get('password').value; // to get value in input tag
    const confirmPassword = AC.get('confirmPassword').value; // to get value in input tag
    if (password !== confirmPassword) {
      AC.get('confirmPassword').setErrors({MatchPassword: true})
    } else {
        return null
    }
}
}  

问题是,如果在编译“新密码”之前更改“确认密码字段”,则表单无效。换句话说,如果我尊重字段的垂直o9rder,一切都没问题,但如果我按不同的顺序编译字段,那么表单仍然无效。

这里是html代码:(正如你所看到的,它有点令人困惑,因为我有其他UX约束,这对应于用户可能的交互)

<form [formGroup]="form" novalidate (ngSubmit)="modal.open()">
        <div class="form-group">
          <label for="oldpassword">Inserisci vecchia password</label>
          <input type="password" id="oldpassword" class="form-control" formControlName="oldpassword">
          <div
            *ngIf="form.controls['oldpassword'].hasError('required') && form.controls['oldpassword'].touched"
            class="alert alert-danger">
            Campo obbligatorio
          </div>
        </div>
        <div class="form-group">
          <label for="password">Inserisci nuova password</label>
          <input type="password" id="password" class="form-control" formControlName="password">
          <div *ngIf="form.controls['password'].hasError('required') && form.controls['password'].touched"
               class="alert alert-danger">
            Campo obbligatorio
          </div>
          <div *ngIf="form.controls['password'].hasError('minlength') && form.controls['password'].touched"
               class="alert alert-danger">
            Lunghezza minima: 4 caratteri.
          </div>
        </div>
        <div class="form-group">
          <label for="confirmPassword">Ripeti nuova password</label>
          <input type="password" class="form-control" id="confirmPassword" formControlName="confirmPassword">
          <div class="alert alert-danger"
               *ngIf="form.errors?.MatchPassword || (form.controls['confirmPassword'].hasError('required') && form.controls['confirmPassword'].touched)">
            Le password non corrispondono
          </div>
        </div>
        <div *ngIf="!this.state.controlloIn; else elseBlock">
          <button type="submit" class="btn btn-primary btn-update" [disabled]="!form.valid || this.controlloInvia">
            Invia Richiesta
          </button>
        </div>
        <ng-template #elseBlock>
          <button type="submit" class="btn btn-primary btn-update" [disabled]="true">
            Invia Richiesta
          </button>
        </ng-template>
      </form>

我不是一个有角度的专家,所以如果你能提出我其他最好的练习,我会非常高兴。感谢所有

4 个答案:

答案 0 :(得分:2)

this.profileForm = this.formBuilder.group({
  password: [this.profile.password, [
    Validators.required,
    Validators.minLength(4)]
  ],
  passwordCheck: [this.profile.password, [
    Validators.required,
    Validators.minLength(4)
  ]],
  oldPassword: [this.profile.oldPassword, [
    Validators.required]],
}, { validator: matchingPasswordsValidator('password', 'passwordCheck') });

这是我用于更改密码的表单。 它使用单独的验证器,该验证器不验证它验证整个表单的字段。

export function matchingPasswordsValidator(passwordKey: string, confirmPasswordKey: string) {
  return (group: FormGroup): { [key: string]: any } => {
    let password = group.controls[passwordKey];
    let confirmPassword = group.controls[confirmPasswordKey];

    if (password.value !== confirmPassword.value) {
      return {
        mismatchedPasswords: true
      };
    }
  }
}

@Directive({
  selector: '[appMatchingPasswordsValidator]',
  providers: [{
    provide: NG_VALIDATORS, useExisting: MatchingPasswordsValidatorDirective, multi: true
  }]
})
export class MatchingPasswordsValidatorDirective {

  constructor() { }

  validate(c: AbstractControl) {
    matchingPasswordsValidator("test", "test");
  }
}

然后这是用于匹配密码的指令。或者您在表格中提供的任何2把钥匙。

答案 1 :(得分:2)

您正在确认字段上直接设置错误。如果您不再触摸该字段,则会在其上设置错误,并且永远不会被删除。仅当字段已被编辑时才对角色运行验证器,因为您可以合理地认为如果某个字段被标记为错误并且尚未编辑,则它仍处于错误状态。

我建议您将此错误直接放在FormGroup上:

static MatchPassword(AC: AbstractControl) {
    const password = AC.get('password').value; // to get value in input tag
    const confirmPassword = AC.get('confirmPassword').value; // to get value in input tag
    if (password !== confirmPassword) {
      return {MatchPassword: true};
    } else {
        return null
    }
}
<div class="alert alert-danger"
               *ngIf="form.errors?.MatchPassword || (form.controls['confirmPassword'].hasError('required') && form.controls['confirmPassword'].touched)">
            Le password non corrispondono
          </div>

答案 2 :(得分:0)

我刚遇到这个问题,发现了一个不同的修复方法。当密码匹配时,我在返回null之前调用AbstractFormControl的updateValueAndValidity函数(onlySelf为true,emitEvent为false)。这使我能够对password和confirmPassword输入进行验证。我可以在密码之前输入确认的密码,并且验证状态正确显示。

static MatchPassword(AC: AbstractControl) {
  const password = AC.get('password').value; 
  const confirmPassword = AC.get('confirmPassword').value; 
  if (password !== confirmPassword) {
    AC.get('confirmPassword').setErrors({MatchPassword: true})
  } else {
    AC.get('confirmPassword').updateValueAndValidity(
             {onlySelf: true, emitEvent: false}
          );
    return null;
  }
}

答案 3 :(得分:0)

我知道这是您问题的较晚答案,但想提供一种方法。 您可以通过在.value上调用ngModel来比较输入的值。

您可以在下面的代码块中看到它的工作原理

 <div *ngIf="newPassword.dirty || newPassword.touched">
    <div class="alert alert-danger" *ngIf="newPassword.value.match(passwordCurrent.value)">
        Current password and New Password can't match.
    </div>
</div>

长版代码                                                                                                                              

    <div class="form-group">
        <div class="input-group input-group-alternative">
            <div class="input-group-prepend">
                                                <span class="input-group-text"><i
                                                        class="fa fa-unlock-alt"></i></span>
            </div>
            <input required minlength="6" [(ngModel)]="passwordOneIn"
                   #newPassword="ngModel" name="newPassword" class="form-control"
                   placeholder="New Password" type="password">
        </div>
    </div>

    <!--#####check if the password and current password match########-->
    <div *ngIf="newPassword.dirty || newPassword.touched">
        <div class="alert alert-danger" *ngIf="newPassword.value.match(passwordCurrent.value)">
            Current password and New Password can't match.
        </div>
    </div>

    <div *ngIf="newPassword.invalid && (newPassword.dirty || newPassword.touched)"
         class="alert alert-danger">
        <div *ngIf="newPassword.errors.required">
            password is required.
        </div>
    </div>

    <div class="form-group">
        <div class="input-group input-group-alternative">
            <div class="input-group-prepend">
                <span class="input-group-text"><i class="fa fa-unlock-alt"></i></span>
            </div>
            <input required minlength="6" [(ngModel)]="passwordTwoIn"
                   #retypedPassword="ngModel" name="retypedPassword"
                   class="form-control" placeholder="Retype Password" type="password">
        </div>
    </div>


    <div *ngIf="retypedPassword.invalid && (retypedPassword.dirty || retypedPassword.touched)"
         class="alert alert-danger">
        <div *ngIf="retypedPassword.errors.required">
            password is required.
        </div>
    </div>

    <!--##### check if the new password and retyped password match ########-->
    <div *ngIf="retypedPassword.dirty || retypedPassword.touched">
        <div class="alert alert-danger" *ngIf="!newPassword.value.match(retypedPassword.value)">
            New password and Retyped Password don't match.
        </div>
    </div>

    <button [disabled]="changePasswordFrom.form.invalid || newPassword.value.match(passwordCurrent.value) || !newPassword.value.match(retypedPassword.value)"
            type="submit" class="btn btn-primary mt-4">Change Password</button>
</div>