web-dev-qa-db-fra.com

La validation personnalisée asynchrone provoque une erreur dans la console: «Impossible de lire la propriété« requise »de null sur Object.eval [en tant que updateDirectives]»

Actuellement, je travaille sur une affectation de formes réactives par Maximilian Schwarzmüller Angular 4 angulaire. Dans la mission, j'ai dû créer une forme réactive, et je l'ai fait. Ensuite, j'ai dû créer un validateur asynchrone personnalisé, qui vérifie la valeur du contrôle. Il ne doit pas être égal à "Test". Voici mon code TypeScript:

import {Component, OnInit} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';

import {Observable} from 'rxjs/Observable';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  statuses = ['Stable', 'Critical', 'Finished'];
  signupForm: FormGroup;

  ngOnInit() {
    this.signupForm = new FormGroup({
      'projectName': new FormControl(null, [Validators.required], this.forbiddenName),
      'email': new FormControl(null, [Validators.required, Validators.email]),
      'projectStatus': new FormControl('Stable')
    });
  }

  onSubmit() {
    console.log(this.signupForm.value);
    console.log(this.signupForm);
  }

  forbiddenName(control: FormControl): Promise<any> | Observable<any> {
    const promise = new Promise<any>((resolve, reject) => {
      setTimeout(() => {
        if (control.value === 'Test') {
          resolve({'projectNameIsForbidden': true});
        } else {
          resolve(null);
        }
      }, 2000);
    });
    return promise;
  }

}

Et voici mon html:

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
      <form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
        <div class="form-group">
          <label for="project-name">Project name</label>
          <input type="text" id="project-name" class="form-control" formControlName="projectName">
          <div class="help-block" *ngIf="!signupForm.get('projectName').valid && signupForm.get('projectName').touched">
            <span *ngIf="signupForm.get('projectName').errors['required']">Can't be empty!<br></span>

            <span *ngIf="signupForm.get('projectName').errors['projectNameIsForbidden']">This name is forbidden!</span>
          </div>
        </div>
        <div class="form-group">
          <label for="email">Email</label>
          <input type="email" id="email" class="form-control" formControlName="email">
          <div class="help-block" *ngIf="!signupForm.get('email').valid && signupForm.get('email').touched">
            <span *ngIf="signupForm.get('email').errors['required']">Can't be blank!<br></span>
            <span *ngIf="signupForm.get('email').errors['email']">Has invalid format!</span>
          </div>
        </div>
        <div class="form-group">
          <label for="project-status">Project Status</label>
          <select id="project-status" class="form-control" formControlName="projectStatus">
            <option *ngFor="let status of statuses">{{ status }}</option>
          </select>
        </div>
        <button class="btn btn-success" type="submit">Submit</button>
      </form>
    </div>
  </div>
</div>

Cela semble fonctionner correctement, cela me donne les messages d'erreur appropriés à mon avis, mais dans la console, je reçois une erreur à chaque keydown dans le contrôle projectName. Voici l'erreur:

enter image description here

Alors, pourquoi l'erreur apparaît? Merci d'avance.

13
Alex Zakruzhetskyi

La cause de l'erreur est ici:

<span *ngIf="signupForm.get('projectName').errors['required']">
   Can't be empty!
</span>

Pendant que vous tapez errors devient null, et si vous vous déplacez du champ avant que le validateur asynchrone n'ait terminé l'évaluation, errors sera null, donc Angular ne peut pas le lire. Cela peut être résolu en utilisant un opérateur de navigation sécurisé:

<span *ngIf="signupForm.get('projectName').errors?.required">

Mais comme je préfère afficher les messages en utilisant hasError, je changerais les deux validations à la place:

<span *ngIf="signupForm.hasError('projectNameIsForbidden', 'projectName')">
<span *ngIf="signupForm.hasError('required', 'projectName')">
48
AJT82