Angular 2表单验证重复密码

Bag*_*yer 60 angular

关于验证器与angular2比较字段,请参阅此问题.不幸的是Angular 2改变了一点,所以解决方案似乎不再起作用了.这是我的代码:

import {IonicApp,Page,NavController,NavParams} from 'ionic/ionic'
import {Component} from 'angular2/core'
import {FORM_PROVIDERS, FormBuilder, Validators} from 'angular2/common'
import {ControlMessages} from '../../components/control-messages'
import {ValidationService} from '../../services/validation-service'

@Page({
  templateUrl: 'build/pages/account/register.html',
  directives: [ControlMessages]
})
export class RegisterPage {

  constructor(nav:NavController,private builder: FormBuilder) {
    this.nav = nav
    this.registerForm = this.builder.group({
      'name' : ['', Validators.required],
      'email' : ['',Validators.compose([Validators.required, ValidationService.emailValidator])],
      'password' : ['',Validators.required],
      'repeat' : ['',this.customValidator]
      }
    )        
  }

  register() {    
    alert(this.registerForm.value.password)
  }

  private customValidator(control) {         
    //console.log(this.registerForm.value.password)
    //return {isEqual: control.value === this.registerForm.value.password}
    return true  
  }
}
Run Code Online (Sandbox Code Playgroud)

我的HTML:

<ion-content class="account">
  <ion-list padding>
    <form [ngFormModel]='registerForm' (submit)='register()'>
      <div class="centered">
        <img class="logo" src="img/logo.png" alt="">
      </div>
      <div class="spacer" style="height: 20px;"></div>

      <ion-input>
        <ion-label floating>Name</ion-label>
        <input type="text" ngControl='name' id='name'>
        <control-messages control="name"></control-messages>            
      </ion-input>

      <ion-input>
        <ion-label floating>Email</ion-label>
        <input type="email" ngControl='email' id='email'>
        <control-messages control="email"></control-messages>               
      </ion-input>

      <ion-input>
        <ion-label floating>Password</ion-label>
        <input type="password" ngControl='password' id='password' value="">
        <control-messages control="password"></control-messages>        
      </ion-input>

      <ion-input>
        <ion-label floating>Confirm Password</ion-label>
        <input type="password" ngControl='repeat' id='repeat'>
        <control-messages control="repeat"></control-messages>                
      </ion-input>

      <button class="calm" full type='submit' [disabled]='!registerForm.valid'>Register</button>

      <ion-item style="background-color:transparent;border:none;">
        <button class="text-button" clear item-right (click)="gotoLogin()">Have an account already, Login</button>
      </ion-item>
    </form>
  </ion-list>

</ion-content>
Run Code Online (Sandbox Code Playgroud)

但遗憾的是,我无法在验证功能中访问"密码"值.如果我取消注释console.log(this.registerForm.value.password),那么我收到以下错误消息:

EXCEPTION:TypeError:无法读取未定义的属性"value"

任何的想法?谢谢.

Thi*_*ier 69

我在你的代码中看到了几个问题.您尝试this在验证程序函数中使用该关键字,但这与组件的实例不对应.这是因为在将其设置为验证器功能时引用该功能.

此外,可以在value物业中达到与控制相关的价值.

也就是说,我认为将两个字段一起验证的正确方法是创建一个组并在其中关联验证器:

import { FormBuilder, Validators } from '@angular/forms';
...
constructor(private fb: FormBuilder) { // <--- inject FormBuilder
  this.createForm();
}
createForm() {
  this.registerForm = this.fb.group({
    'name' : ['', Validators.required],
    'email': ['', [Validators.required, Validators.email] ],
    'passwords': this.fb.group({
      password: ['', Validators.required],
      repeat:   ['', Validators.required]
    }, {validator: this.matchValidator})
  });    
}
Run Code Online (Sandbox Code Playgroud)

这样您就可以访问该组的所有控件,而不仅仅是一个,并且不再需要使用this关键字...可以使用controlsFormGroup 的属性访问组的表单控件.触发验证时提供FormGroup.例如:

matchValidator(group: FormGroup) {
  var valid = false;

  for (name in group.controls) {
    var val = group.controls[name].value
    (...)
  }

  if (valid) {
    return null;
  }

  return {
    mismatch: true
  };
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅此anwer:

编辑

要显示错误,您只需使用以下内容:

<span *ngIf="!registerForm.passwords.valid" class="help-block text-danger">
  <div *ngIf="registerForm.passwords?.errors?.mismatch">
    The two passwords aren't the same
  </div>
</span>
Run Code Online (Sandbox Code Playgroud)


Sla*_* II 23

我已经为Angular 4实现了自定义密码匹配验证器.

除了检查两个值是否匹配之外,它还订阅了来自其他控件的更改,并在更新两个控件中的任何一个时重新验证.您可以将其作为自己实现的参考,也可以直接复制.

以下是该解决方案的链接: https ://gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30.


在这里,我提供了代码的副本:

比赛等,validator.ts

import {FormControl} from '@angular/forms';


export function matchOtherValidator (otherControlName: string) {

  let thisControl: FormControl;
  let otherControl: FormControl;

  return function matchOtherValidate (control: FormControl) {

    if (!control.parent) {
      return null;
    }

    // Initializing the validator.
    if (!thisControl) {
      thisControl = control;
      otherControl = control.parent.get(otherControlName) as FormControl;
      if (!otherControl) {
        throw new Error('matchOtherValidator(): other control is not found in parent group');
      }
      otherControl.valueChanges.subscribe(() => {
        thisControl.updateValueAndValidity();
      });
    }

    if (!otherControl) {
      return null;
    }

    if (otherControl.value !== thisControl.value) {
      return {
        matchOther: true
      };
    }

    return null;

  }

}
Run Code Online (Sandbox Code Playgroud)

用法

以下是如何将其与反应形式一起使用:

private constructForm () {
  this.form = this.formBuilder.group({
    email: ['', [
      Validators.required,
      Validators.email
    ]],
    password: ['', Validators.required],
    repeatPassword: ['', [
      Validators.required,
      matchOtherValidator('password')
    ]]
  });
}
Run Code Online (Sandbox Code Playgroud)

可在此处找到更多最新的验证器:moebius-mlm/ng-validators.


dan*_*nto 12

找到了更简单的解决方案.不确定这是否是正确的方法,但它适用于我

<!-- PASSWORD -->
<ion-item [ngClass]="{'has-error': !signupForm.controls.password.valid && signupForm.controls.password.dirty}">
    <ion-input formControlName="password" type="password" placeholder="{{ 'SIGNUP.PASSWORD' | translate }}" [(ngModel)]="registerCredentials.password"></ion-input>
</ion-item>

<!-- VERIFY PASSWORD -->
<ion-item [ngClass]="{'has-error': !signupForm.controls.verify.valid && signupForm.controls.verify.dirty}">
       <ion-input formControlName="verify" [(ngModel)]="registerCredentials.verify" type="password" pattern="{{registerCredentials.password}}" placeholder="{{ 'SIGNUP.VERIFY' | translate }}"> </ion-input>
</ion-item>
Run Code Online (Sandbox Code Playgroud)

看到

pattern="{{registerCredentials.password}}"
Run Code Online (Sandbox Code Playgroud)

  • 小心,密码匹配将失败,如果密码包含特殊字符,如*(星) (4认同)

Mix*_*OID 9

Angular 4.3.3解决方案!

您可以使用做到这一点:[formGroup],formGroupName,formControlNameHTML和new FormGroup,new FormControl和自定义areEqual在TS方法

reg.component.html

<div [formGroup]="userFormPassword">
  <div>
    <input formControlName="current_password" type="password" placeholder="Current Password">
  </div>

  <div formGroupName="passwords">
    <input formControlName="new_password" type="password" placeholder="New Password">
  </div>

  <div formGroupName="passwords">
    <input formControlName="repeat_new_password" type="password" class="form-control" placeholder="Repeat New Password">
    <div class="input-error" *ngIf="
          userFormPassword.controls['passwords'].errors &&
          userFormPassword.controls['passwords'].errors.areEqual &&
          userFormPassword.controls['passwords'].controls.repeat_new_password.touched &&
          userFormPassword.controls['passwords'].controls.new_password.touched
        ">PASSWORDS do not match
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

reg.component.ts

export class HomeHeaderSettingsModalComponent implements OnInit {
  userFormPassword: FormGroup;
  // ...

  static areEqual(c: AbstractControl): ValidationErrors | null {
    const keys: string[] = Object.keys(c.value);
    for (const i in keys) {
      if (i !== '0' && c.value[ keys[ +i - 1 ] ] !== c.value[ keys[ i ] ]) {
        return { areEqual: true };
      }
    }
  }

  ngOnInit() {
    this.userFormPassword = new FormGroup({
      'current_password': new FormControl(this.user.current_password, [
        Validators.required,
      ]),
      'passwords': new FormGroup({
        'new_password': new FormControl(this.user.new_password, [
          Validators.required
        ]),
        'repeat_new_password': new FormControl(this.user.repeat_new_password, [
          Validators.required
        ])
      }, HomeHeaderSettingsModalComponent.areEqual)
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

结果: 结果


Cha*_*ang 5

如果您使用的是 RC.5 并且找不到 ControlGroup,您可以尝试使用 FormGroup。你可以从我的回答中找到更多信息:

用于密码重复的 Angular 2 RC.5 表单验证


小智 5

Summary

  • Trigger validation every time the value of the other control changes.
  • Unsubscribe to avoid memory leaks
  • returning {match: true} will allow us check if a given control has the error using myControl.hasError('match')

Implementation

import { AbstractControl, ValidatorFn } from '@angular/forms';
import { Subscription } from 'rxjs/Subscription';

export function matchOtherValidator(otherControlName: string): ValidatorFn {
    return (control: AbstractControl): { [key: string]: any } => {
        const otherControl: AbstractControl = control.root.get(otherControlName);

        if (otherControl) {
            const subscription: Subscription = otherControl
                .valueChanges
                .subscribe(() => {
                    control.updateValueAndValidity();
                    subscription.unsubscribe();
                });
        }

        return (otherControl && control.value !== otherControl.value) ? {match: true} : null;
    };
}
Run Code Online (Sandbox Code Playgroud)

Example

this.registerForm = formBuilder.group({
            email: ['', [
                Validators.required, Validators.email
            ]],
            password: ['', [
                Validators.required, Validators.minLength(8)
            ]],
            confirmPassword: ['', [
                Validators.required, matchOtherValidator('password')
            ]]
        });
Run Code Online (Sandbox Code Playgroud)