2
votes

Comment puis-je atteindre les variables de composant dans le validateur personnalisé?

Je souhaite créer un validateur personnalisé qui rendrait le bouton d'envoi disponible uniquement si le texte du formulaire est unique. J'ai une instance VulnarabilitiesClass, qui contient un tableau d'objets avec des champs id et name. Après avoir tapé du texte dans mon formulaire, j'obtiens cette erreur: Erreur: undefined n'est pas un objet (évaluation de 'this.systemVulnarabilities')

this.systemVulnarabilities = new VulnarabilitiesClass();

profileForm = this.fb.group({
    name: ['', Validators.required,this.UniqueNameValidator],
  });

private UniqueNameValidator(control: FormControl): ValidationErrors{
  let vulnarabilityName: string = control.value;
  console.log(vulnarabilityName);
  console.log(this.systemVulnarabilities.displayList.toString());//no output already
  let found: number = this.systemVulnarabilities.displayList.map(function(e) { return e.name; }).indexOf(vulnarabilityName); //mistake
  if(found === -1){
    return {invalidPassword: 'this name already exists'};
  }
  return null;
}
<form [formGroup]="profileForm">
  <label>
    Vulnarability Name:
    <input type="text" formControlName="name" required>
  </label>
</form>

<p>
  Form Status: {{ profileForm.status }}
</p>
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<button type="submit" [disabled]="!profileForm.valid">Submit</button>


2 commentaires

Pouvez-vous montrer votre code de classe de vulnérabilité?


peut-être afficher plus de code de classe de composant. Si "this.systemVulnarabilities n'est pas défini", il n'est certainement pas correctement instancié.


3 Réponses :


4
votes

Cette erreur se produit car la méthode UniqueNameValidator est exécutée avec un contexte de composant différent de this . La raison en est que dans le contexte javascript cela dépend de la manière dont la fonction est exécutée et non de l'endroit où elle a été déclarée.

La solution simple consiste à utiliser Function.prototype.bind qui garantit un contexte correct ce

name: ['', [Validators.required, this.UniqueNameValidator.bind(this)]],

De plus, si votre validateur est synchrone, vous devez envelopper vos validateurs dans un tableau sinon Angular le traitera comme un validateur asynchrone:

this.UniqueNameValidator.bind(this)


0 commentaires

1
votes

l'autre manière "classique" est de définir la fonction comme

profileForm = this.fb.group({
    name: ['', Validators.required,this.UniqueNameValidator()],
  });

et d'ajouter le validateur -voir le () à la fin de UniqueName Validator

private UniqueNameValidator(){
  return (control: FormControl)=>{
         ....
  }
}


0 commentaires

0
votes

Je pense que vous pourriez utiliser une fermeture et rendre votre Validateur contextuel avec la variable systemVulnarabilities , comme ceci:

UniqueNameValidator(systemVulnarabilities): ValidatorFn {
  return (control: FormControl)=>{
    let vulnarabilityName: string = control.value;
  let found: number = systemVulnarabilities.displayList.map(function(e) { return e.name; }).indexOf(vulnarabilityName); //mistake
  if(found === -1){
    return {invalidPassword: 'this name already exists'};
  }
  return null;
  }
}

profileForm = this.fb.group({
    name: ['', Validators.required,this.UniqueNameValidator(systemVulnarabilities)],
  });


0 commentaires