RangeError: le Maximum de la pile d'appels de taille dépassé lors de l'utilisation de valueChanges.abonnez-vous
Je suis en utilisant Angulaire 5 avec des formes Réactives et ont besoin de faire usage de la valueChanges afin de désactiver les exigences relatives à la validation dynamiquement
classe de composant:
export class UserEditor implements OnInit {
public userForm: FormGroup;
userName: FormControl;
firstName: FormControl;
lastName: FormControl;
email: FormControl;
loginTypeId: FormControl;
password: FormControl;
confirmPassword: FormControl;
...
ngOnInit() {
this.createFormControls();
this.createForm();
this.userForm.get('loginTypeId').valueChanges.subscribe(
(loginTypeId: string) => {
console.log("log this!");
if (loginTypeId === "1") {
console.log("disable validators");
Validators.pattern('^[0-9]{5}(?:-[0-9]{4})?$')]);
this.userForm.get('password').setValidators([]);
this.userForm.get('confirmPassword').setValidators([]);
} else if (loginTypeId === '2') {
console.log("enable validators");
this.userForm.get('password').setValidators([Validators.required, Validators.minLength(8)]);
this.userForm.get('confirmPassword').setValidators([Validators.required, Validators.minLength(8)]);
}
this.userForm.get('loginTypeId').updateValueAndValidity();
}
)
}
createFormControls() {
this.userName = new FormControl('', [
Validators.required,
Validators.minLength(4)
]);
this.firstName = new FormControl('', Validators.required);
this.lastName = new FormControl('', Validators.required);
this.email = new FormControl('', [
Validators.required,
Validators.pattern("[^ @]*@[^ @]*")
]);
this.password = new FormControl('', [
Validators.required,
Validators.minLength(8)
]);
this.confirmPassword = new FormControl('', [
Validators.required,
Validators.minLength(8)
]);
}
createForm() {
this.userForm = new FormGroup({
userName: this.userName,
name: new FormGroup({
firstName: this.firstName,
lastName: this.lastName,
}),
email: this.email,
loginTypeId: this.loginTypeId,
password: this.password,
confirmPassword: this.confirmPassword
});
}
Cependant quand je le lance j'obtiens un navigateur javascript erreur
UserEditor.html:82 ERROR RangeError: Maximum call stack size exceeded
at SafeSubscriber.tryCatcher (tryCatch.js:9)
at SafeSubscriber.webpackJsonp.../../../../rxjs/_esm5/Subscription.js.Subscription.unsubscribe (Subscription.js:68)
at SafeSubscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.Subscriber.unsubscribe (Subscriber.js:124)
at SafeSubscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:242)
at SafeSubscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.SafeSubscriber.next (Subscriber.js:186)
at Subscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.Subscriber._next (Subscriber.js:127)
at Subscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.Subscriber.next (Subscriber.js:91)
at EventEmitter.webpackJsonp.../../../../rxjs/_esm5/Subject.js.Subject.next (Subject.js:56)
at EventEmitter.webpackJsonp.../../../core/esm5/core.js.EventEmitter.emit (core.js:4319)
at FormControl.webpackJsonp.../../../forms/esm5/forms.js.AbstractControl.updateValueAndValidity (forms.js:3377)
"journal!" est loggedcalled à plusieurs reprises comme elle est appelée récursivement c'est pourquoi leur est une pile d'erreur
Si je supprime le valueChanges.inscrire le code du travail en dehors de la suppression de la validation conditionnelle.
Pourquoi est-il l'appel de valueChanges.abonnez-vous de manière récursive?
N'est-ce pas parce que vous appelez
Je suis d'accord avec ConnorsFan,
c'est la raison de la récursion. Je ne devrais pas mettre à jour le même domaine, je suis suivi pour le changement. Code était censé être".objet userForm.get('loginTypeId').'. Vous pouvez le mettre dans une réponse
updateValueAndValidity()
à la fin de la gestionnaire d'événement?Je suis d'accord avec ConnorsFan,
updateValueAndValidity()
est probablement à l'origine valueChanges à feu, encore une fois, ce qui provoque une boucle infiniec'est la raison de la récursion. Je ne devrais pas mettre à jour le même domaine, je suis suivi pour le changement. Code était censé être".objet userForm.get('loginTypeId').'. Vous pouvez le mettre dans une réponse
OriginalL'auteur dfmetro | 2017-12-14
Vous devez vous connecter pour publier un commentaire.
Le problème, c'est que vous modifiez la valeur du champ à l'intérieur de la
valueChanges
gestionnaire d'événement pour le même domaine, provoquant l'événement qui se déclenche à nouveau:this.userForm.get('password').updateValueAndValidity();this.userForm.get('confirmPassword').updateValueAndValidity();
OriginalL'auteur ConnorsFan
Essayez d'ajouter
distinctUntilChanged()
dans le pipeline juste avantsubscribe()
. Il doit filtrer ces "changement" des événements où la valeur n'a pas réellement changé.valueChanges
sur de multiples et dépendent les uns des autresformControls
. Merci!OriginalL'auteur Alexander Leonov
Eh bien, en fait, la véritable réponse est, si vous voulez vous abonner à toute forme de changements et encore courir patchValue à l'intérieur, alors vous devriez juste ajouter {emitEvent: false} option pour patchValue, donc la correction aura pas déclencher une autre détection de changement de
code:
PS. C'est aussi moins fastidieux que de souscrire à chaque contrôle de formulaire, un par un pour éviter le déclenchement de changement de max de la pile des appels dépassé. Surtout si vous formulaire a 100 contrôles de vous abonner.
Maintenant à élaborer d'autres, si vous avez encore besoin de updateValueAndValidity à l'intérieur de l'abonnement, alors je vous suggérons d'utiliser le distinctUntilChanged rxjs opérateur, uniquement l'exécution de l'abonnement, lors de certains changements de valeur.
Maintenant, nous allons également faire une validation personnalisée de la fonction, parce que, par défaut, distinctUntilChanged valide les objets par pointeur et le pointeur est de nouveau à chaque changement.
Et voila, nous sommes les correctifs et la mise à jour, sans que le maximum de la pile d'appel!
OriginalL'auteur Karl Johan Vallner
Ma réponse est juste développement de cette une.
En ajoutant
distinctUntilChanged()
dans le pipeline juste avantsubscribe()
vous éviter le "Maximum de la pile des appels taille dépassé" parce queL'utilisation:
La Documentation
OriginalL'auteur mpro