Код прыгает прямо в валидатор и ломает все - PullRequest
1 голос
/ 07 апреля 2019

Я написал свои собственные валидаторы для проверки полей ввода моей реактивной формы, но, похоже, они не работают.Первые два никогда не выдают ошибку, а последний ломает все, как только я добавляю его в свой код.С помощью augury я отлаживал все, что мог, и обнаружил, что с помощью 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 Ответ

1 голос
/ 07 апреля 2019

Учитывая, что пользовательский валидатор validatePassword включает перекрестную валидацию (валидация по нескольким полям - FormControls password и passwordConfirmation), вы должны передавать этот валидатор во втором аргументеинициализация формы register.

Вы можете оставить остальные элементы FormControls такими, какие они есть.Удалите validatePassword из passwordConfirmation и добавьте его ко второму аргументу formBuilder.

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

Что касается вашей второй проблемы, то это потому, что register FormGroup не определена, когда страницаоказаны.Вы должны переместить его в свой конструктор или просто инициализировать FormControls, когда вы объявляете свойство 'register' в вашем классе.

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
   .
  })
...