代码直接跳入验证器并破坏所有内容

时间:2019-04-07 17:44:16

标签: angular validation customvalidator

我已经扭曲了自己的验证器,以检查我的反应形式的输入字段,但是它们似乎不起作用。前两个完全不会产生错误,而后一个一旦我将其添加到代码中就会破坏所有内容。我一直在尽我所能地调试调试程序,结果发现,通过我的validatePasswords,他立即跳入了该方法,而我什至没有碰过任何东西。如果你们中的任何一个能弄清楚为什么会这样做或为什么我的其他验证器永远不会产生错误,那真是太神奇了!

我的3个自定义验证器

function validateEmail(control: FormGroup): { [key: string]: any } {
  var mailReg = /^([a-zA-Z]+[a-zA-Z0-9.\-_éèàùäëïöüâêîôû]*)@([a-z]+)[.]([a-z]+)([.][a-z]+)*$/g;
  if (!mailReg.test(control.get('email').value)) {
    return { noValidEmail: true };
  }
  return null;
}
function validatePhone(control: FormGroup): { [key: string]: any } {
  var phoneReg = /^0{0,2}(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{7,14}$/;
  if (!phoneReg.test(control.get('phone').value)) {
    return { noValidPhone: true };
  }
  return null;
}

function validatePassword(control: FormGroup): { [key: string]: any } {
  if (
    control.get('password').value !== control.get('passwordConfirmation').value
  ) {
    return { noMatchingPasswords: true };
  }
  return null;
}

我的构造函数和形式:

 public register: FormGroup;
  constructor(
    public dialogRef: MatDialogRef<RegisterFormComponent>,
    private fb: FormBuilder,
    private http: HttpClient
  ) {}

  ngOnInit() {
    this.register = this.fb.group({
      firstName: ['', [Validators.required, Validators.minLength(2)]],
      lastName: ['', [Validators.required, Validators.minLength(2)]],
      email: [
        '',
        [Validators.required, Validators.minLength(5)],
        validateEmail
      ],
      phone: [
        '',
        [Validators.required, Validators.minLength(8)],
        validatePhone
      ],
      country: [''],
      password: ['', [Validators.required, Validators.minLength(5)]],
      passwordConfirmation: [
        '',
        [Validators.required, Validators.minLength(5), validatePassword]
      ]
    });
  }

我的错误消息方法

  getErrorMessage(errors: any) {
    if (errors.required) {
      return 'is required';
    } else if (errors.noValidEmail) {
      return 'not a valid email';
    } else if (errors.noValidPhone) {
      return 'no valid phone number';
    } else if (errors.noMatchingPasswords) {
      return 'passwords don\'t match';
    } else if (errors.minlength) {
      return `need at least ${errors.minlength.requiredLength} characters`;
    }
  }

它产生的错误:

ERROR TypeError: Cannot read property 'get' of undefined
    at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.addControl (forms.js:5280)
    at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName._setUpControl (forms.js:5882)
    at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName.ngOnChanges (forms.js:5803)
    at checkAndUpdateDirectiveInline (core.js:22085)
    at checkAndUpdateNodeInline (core.js:23353)
    at checkAndUpdateNode (core.js:23315)
    at debugCheckAndUpdateNode (core.js:23949)
    at debugCheckDirectivesFn (core.js:23909)
    at Object.eval [as updateDirectives] (RegisterFormComponent.html:5)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:23901)

最后,我的HTML表单

<h3 mat-dialog-title>Register</h3>
<mat-dialog-content>
  <form [formGroup]="register" (ngSubmit)="onSubmit()">
    <mat-form-field>
      <input matInput aria-label="First name" placeholder="First name" type="text" formControlName="firstName"
        class="browser-default" required />
      <mat-error *ngIf="register.get('firstName')['errors'] && register.get('firstName').touched">
        {{ getErrorMessage(register.get('firstName')['errors']) }}
      </mat-error>
    </mat-form-field>
    <mat-form-field>
      <input matInput aria-label="Last name" placeholder="Last name" type="text" formControlName="lastName"
        class="browser-default" required />
      <mat-error *ngIf="register.get('lastName')['errors'] && register.get('lastName').touched">
        {{ getErrorMessage(register.get('lastName')['errors']) }}
      </mat-error>
    </mat-form-field>
    <mat-form-field>
      <input matInput aria-label="Email" placeholder="Email" type="text" formControlName="email" class="browser-default"
        required />
      <mat-error *ngIf="register.get('email')['errors'] && register.get('email').touched">
        {{ getErrorMessage(register.get('email')['errors']) }}
      </mat-error>
    </mat-form-field>
    <mat-form-field>
      <input matInput aria-label="Phone" placeholder="Phone" type="text" formControlName="phone" class="browser-default"
        required />
      <mat-error *ngIf="register.get('phone')['errors'] && register.get('phone').touched">
        {{ getErrorMessage(register.get('phone')['errors']) }}
      </mat-error>
    </mat-form-field>
    <mat-form-field>
      <input matInput aria-label="Country" placeholder="Country" type="text" formControlName="country"
        class="browser-default" />
    </mat-form-field>
    <mat-form-field>
      <input matInput aria-label="Password" placeholder="Password" type="password" formControlName="password"
        class="browser-default" required />
      <mat-error *ngIf="register.get('password')['errors'] && register.get('password').touched">
        {{ getErrorMessage(register.get('password')['errors']) }}
      </mat-error>
    </mat-form-field>
    <mat-form-field>
      <input matInput aria-label="Confirmation Password" placeholder="Confirmation Password" type="password"
        formControlName="passwordConfirmation" class="browser-default" required />
      <mat-error *ngIf="register.get('passwordConfirmation')['errors'] && register.get('passwordConfirmation').touched">
        {{ getErrorMessage(register.get('passwordConfirmation')['errors']) }}
      </mat-error>
    </mat-form-field>
    <div class="buttonDiv">
      <button mat-button (click)="onNoClick()">Cancel</button>
      <button mat-button type="submit" [disabled]="!register.valid">Register</button>
    </div>
  </form>
</mat-dialog-content>

更新:

这些错误是新错误,但现在也抛出:

ERROR Error: formGroup expects a FormGroup instance. Please pass one in.

       Example:


    <div [formGroup]="myGroup">
      <input formControlName="firstName">
    </div>

    In your class:

    this.myGroup = new FormGroup({
       firstName: new FormControl()
    });
    at Function.push../node_modules/@angular/forms/fesm5/forms.js.ReactiveErrors.missingFormException (forms.js:1443)
    at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective._checkFormPresent (forms.js:5414)
    at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.ngOnChanges (forms.js:5237)
    at checkAndUpdateDirectiveInline (core.js:22085)
    at checkAndUpdateNodeInline (core.js:23353)
    at checkAndUpdateNode (core.js:23315)
    at debugCheckAndUpdateNode (core.js:23949)
    at debugCheckDirectivesFn (core.js:23909)
    at Object.eval [as updateDirectives] (RegisterFormComponent.html:3)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:23901)

ERROR TypeError: Cannot read property 'value' of null
    at validatePassword (register-form.component.ts:29)
    at forms.js:658
    at Array.map (<anonymous>)
    at _executeValidators (forms.js:658)
    at FormControl.validator (forms.js:623)
    at FormControl.push../node_modules/@angular/forms/fesm5/forms.js.AbstractControl._runValidator (forms.js:2914)
    at FormControl.push../node_modules/@angular/forms/fesm5/forms.js.AbstractControl.updateValueAndValidity (forms.js:2890)
    at new FormControl (forms.js:3241)
    at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder.control (forms.js:6462)
    at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder._createControl (forms.js:6502)

(第29行是:control.get('password').value !== control.get('passwordConfirmation').value

1 个答案:

答案 0 :(得分:1)

鉴于validatePassword自定义验证器涉及cross-field validation(跨多个字段的验证-FormControls passwordpasswordConfirmation),您应该在第二个参数中传递该验证器register表单的初始化。

您可以保持其他FormControl不变。从passwordConfirmation中删除validatePassword,并将其添加到formBuilder的第二个参数中。

this.register = this.fb.group({
  .
  .
  password: ['', [Validators.required, Validators.minLength(5)]],
  passwordConfirmation: [
    '',
    [Validators.required, Validators.minLength(5)]
  ]
}, { validators: validatePassword });

对于第二个问题,这是因为呈现页面时register FormGroup是未定义的。您应该将其移到构造函数中,或者在类上声明“ register”属性时简单地初始化FormControl。

constructor(
    public dialogRef: MatDialogRef<RegisterFormComponent>,
    private fb: FormBuilder,
    private http: HttpClient
  ) {
    this.register = fb.group({ 
      .
      .
      // your FormControls
      .
    });
  }

export class YourComponent implements OnInit {

  public register: FormGroup = this.fb.group({ 
   .
   .
   // your FormControls
   .
  })