RangeError: Maximum call stack size exceeded when using valueChanges.subscribe





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







8















I am using Angular 5 with Reactive forms and need to make use of the valueChanges in order to disable required validation dynamically



component class:



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


However when I run it I get a browser javascript error



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)


"log this!" is loggedcalled repeatedly like it is called recursively which is why their is a stack error



If I remove the valueChanges.subscribe the code work apart from removing the validation conditionally.



Why is it calling valueChanges.subscribe recursively?










share|improve this question




















  • 1





    Isn't it because you call updateValueAndValidity() at the end of the event handler?

    – ConnorsFan
    Dec 14 '17 at 20:52











  • I agree with ConnorsFan, updateValueAndValidity() is probably causing valueChanges to fire again, causing an infinite loop

    – LLai
    Dec 14 '17 at 21:25











  • @ConnorsFan thats the reason for the recursion. I shouldn't update the same field I am monitoring for change. Code was meant to be 'this.userForm.get('loginTypeId').'. You can put it in an answer

    – dfmetro
    Dec 14 '17 at 21:43


















8















I am using Angular 5 with Reactive forms and need to make use of the valueChanges in order to disable required validation dynamically



component class:



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


However when I run it I get a browser javascript error



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)


"log this!" is loggedcalled repeatedly like it is called recursively which is why their is a stack error



If I remove the valueChanges.subscribe the code work apart from removing the validation conditionally.



Why is it calling valueChanges.subscribe recursively?










share|improve this question




















  • 1





    Isn't it because you call updateValueAndValidity() at the end of the event handler?

    – ConnorsFan
    Dec 14 '17 at 20:52











  • I agree with ConnorsFan, updateValueAndValidity() is probably causing valueChanges to fire again, causing an infinite loop

    – LLai
    Dec 14 '17 at 21:25











  • @ConnorsFan thats the reason for the recursion. I shouldn't update the same field I am monitoring for change. Code was meant to be 'this.userForm.get('loginTypeId').'. You can put it in an answer

    – dfmetro
    Dec 14 '17 at 21:43














8












8








8


2






I am using Angular 5 with Reactive forms and need to make use of the valueChanges in order to disable required validation dynamically



component class:



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


However when I run it I get a browser javascript error



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)


"log this!" is loggedcalled repeatedly like it is called recursively which is why their is a stack error



If I remove the valueChanges.subscribe the code work apart from removing the validation conditionally.



Why is it calling valueChanges.subscribe recursively?










share|improve this question
















I am using Angular 5 with Reactive forms and need to make use of the valueChanges in order to disable required validation dynamically



component class:



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


However when I run it I get a browser javascript error



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)


"log this!" is loggedcalled repeatedly like it is called recursively which is why their is a stack error



If I remove the valueChanges.subscribe the code work apart from removing the validation conditionally.



Why is it calling valueChanges.subscribe recursively?







angular typescript angular5 angular-reactive-forms






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 26 '18 at 13:44









mpro

1,96421021




1,96421021










asked Dec 14 '17 at 20:49









dfmetrodfmetro

1,53232144




1,53232144








  • 1





    Isn't it because you call updateValueAndValidity() at the end of the event handler?

    – ConnorsFan
    Dec 14 '17 at 20:52











  • I agree with ConnorsFan, updateValueAndValidity() is probably causing valueChanges to fire again, causing an infinite loop

    – LLai
    Dec 14 '17 at 21:25











  • @ConnorsFan thats the reason for the recursion. I shouldn't update the same field I am monitoring for change. Code was meant to be 'this.userForm.get('loginTypeId').'. You can put it in an answer

    – dfmetro
    Dec 14 '17 at 21:43














  • 1





    Isn't it because you call updateValueAndValidity() at the end of the event handler?

    – ConnorsFan
    Dec 14 '17 at 20:52











  • I agree with ConnorsFan, updateValueAndValidity() is probably causing valueChanges to fire again, causing an infinite loop

    – LLai
    Dec 14 '17 at 21:25











  • @ConnorsFan thats the reason for the recursion. I shouldn't update the same field I am monitoring for change. Code was meant to be 'this.userForm.get('loginTypeId').'. You can put it in an answer

    – dfmetro
    Dec 14 '17 at 21:43








1




1





Isn't it because you call updateValueAndValidity() at the end of the event handler?

– ConnorsFan
Dec 14 '17 at 20:52





Isn't it because you call updateValueAndValidity() at the end of the event handler?

– ConnorsFan
Dec 14 '17 at 20:52













I agree with ConnorsFan, updateValueAndValidity() is probably causing valueChanges to fire again, causing an infinite loop

– LLai
Dec 14 '17 at 21:25





I agree with ConnorsFan, updateValueAndValidity() is probably causing valueChanges to fire again, causing an infinite loop

– LLai
Dec 14 '17 at 21:25













@ConnorsFan thats the reason for the recursion. I shouldn't update the same field I am monitoring for change. Code was meant to be 'this.userForm.get('loginTypeId').'. You can put it in an answer

– dfmetro
Dec 14 '17 at 21:43





@ConnorsFan thats the reason for the recursion. I shouldn't update the same field I am monitoring for change. Code was meant to be 'this.userForm.get('loginTypeId').'. You can put it in an answer

– dfmetro
Dec 14 '17 at 21:43












4 Answers
4






active

oldest

votes


















7














The problem is that you modify the value of the field inside of the valueChanges event handler for that same field, causing the event to be triggered again:



this.userForm.get('loginTypeId').valueChanges.subscribe(
(loginTypeId: string) => {
...
this.userForm.get('loginTypeId').updateValueAndValidity(); <-- Triggers valueChanges!
}





share|improve this answer


























  • Yes thanks I had to change to this.userForm.get('password').updateValueAndValidity();this.userForm.get('confirmPassword').updateValueAndValidity();

    – dfmetro
    Dec 15 '17 at 4:35



















8














Try adding distinctUntilChanged() in the pipeline just before subscribe(). It should filter out those "change" events where value was not actually changed.






share|improve this answer



















  • 1





    This is universal solution, which works also in the case when you perform valueChanges on multiple and dependent on each others formControls. Thanks!

    – mpro
    Nov 26 '18 at 11:26





















8














Well actually, the true answer is, if you want to subscribe to any form changes and still run patchValue inside it, then you should just add the {emitEvent: false} option to patchValue, thus the patching will not trigger another change detection



code:



this.formGroup
.valueChanges
.subscribe( _ => {
this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
} );


PS. This is also less tedious than subscribing to each form control one-by-one to avoid triggering change max call stack exceeded. Especially if you form has 100 controls to subscribe to.



Now to elaborate further, if you still need to updateValueAndValidity inside the subscription, then I suggest you use the distinctUntilChanged rxjs operator, to only run the subscription, when some value changes.



Now we will also have to make it a custom validation function, because by default, distinctUntilChanged validates objects by pointer and the pointer is new on every change.



this.formGroup
.valueChanges
.distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
.subscribe( _ => {
this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
this.formGroup.get( 'controlName' ).updateValueAndValidity();
} );


And voila, we are patching and updating, without running into the maximum call stack!






share|improve this answer

































    5














    My answer is just development of this one.



    By adding distinctUntilChanged() in the pipeline just before subscribe() you avoid the "Maximum call stack size exceeded" because




    distinctUntilChanged method only emit when the current value is different than the last.




    The usage:



    this.userForm.get('password')
    .valueChanges.pipe(distinctUntilChanged())
    .subscribe(val => {})


    Documentation






    share|improve this answer
























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f47821809%2frangeerror-maximum-call-stack-size-exceeded-when-using-valuechanges-subscribe%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      7














      The problem is that you modify the value of the field inside of the valueChanges event handler for that same field, causing the event to be triggered again:



      this.userForm.get('loginTypeId').valueChanges.subscribe(
      (loginTypeId: string) => {
      ...
      this.userForm.get('loginTypeId').updateValueAndValidity(); <-- Triggers valueChanges!
      }





      share|improve this answer


























      • Yes thanks I had to change to this.userForm.get('password').updateValueAndValidity();this.userForm.get('confirmPassword').updateValueAndValidity();

        – dfmetro
        Dec 15 '17 at 4:35
















      7














      The problem is that you modify the value of the field inside of the valueChanges event handler for that same field, causing the event to be triggered again:



      this.userForm.get('loginTypeId').valueChanges.subscribe(
      (loginTypeId: string) => {
      ...
      this.userForm.get('loginTypeId').updateValueAndValidity(); <-- Triggers valueChanges!
      }





      share|improve this answer


























      • Yes thanks I had to change to this.userForm.get('password').updateValueAndValidity();this.userForm.get('confirmPassword').updateValueAndValidity();

        – dfmetro
        Dec 15 '17 at 4:35














      7












      7








      7







      The problem is that you modify the value of the field inside of the valueChanges event handler for that same field, causing the event to be triggered again:



      this.userForm.get('loginTypeId').valueChanges.subscribe(
      (loginTypeId: string) => {
      ...
      this.userForm.get('loginTypeId').updateValueAndValidity(); <-- Triggers valueChanges!
      }





      share|improve this answer















      The problem is that you modify the value of the field inside of the valueChanges event handler for that same field, causing the event to be triggered again:



      this.userForm.get('loginTypeId').valueChanges.subscribe(
      (loginTypeId: string) => {
      ...
      this.userForm.get('loginTypeId').updateValueAndValidity(); <-- Triggers valueChanges!
      }






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 14 '17 at 21:58

























      answered Dec 14 '17 at 21:52









      ConnorsFanConnorsFan

      32.3k43564




      32.3k43564













      • Yes thanks I had to change to this.userForm.get('password').updateValueAndValidity();this.userForm.get('confirmPassword').updateValueAndValidity();

        – dfmetro
        Dec 15 '17 at 4:35



















      • Yes thanks I had to change to this.userForm.get('password').updateValueAndValidity();this.userForm.get('confirmPassword').updateValueAndValidity();

        – dfmetro
        Dec 15 '17 at 4:35

















      Yes thanks I had to change to this.userForm.get('password').updateValueAndValidity();this.userForm.get('confirmPassword').updateValueAndValidity();

      – dfmetro
      Dec 15 '17 at 4:35





      Yes thanks I had to change to this.userForm.get('password').updateValueAndValidity();this.userForm.get('confirmPassword').updateValueAndValidity();

      – dfmetro
      Dec 15 '17 at 4:35













      8














      Try adding distinctUntilChanged() in the pipeline just before subscribe(). It should filter out those "change" events where value was not actually changed.






      share|improve this answer



















      • 1





        This is universal solution, which works also in the case when you perform valueChanges on multiple and dependent on each others formControls. Thanks!

        – mpro
        Nov 26 '18 at 11:26


















      8














      Try adding distinctUntilChanged() in the pipeline just before subscribe(). It should filter out those "change" events where value was not actually changed.






      share|improve this answer



















      • 1





        This is universal solution, which works also in the case when you perform valueChanges on multiple and dependent on each others formControls. Thanks!

        – mpro
        Nov 26 '18 at 11:26
















      8












      8








      8







      Try adding distinctUntilChanged() in the pipeline just before subscribe(). It should filter out those "change" events where value was not actually changed.






      share|improve this answer













      Try adding distinctUntilChanged() in the pipeline just before subscribe(). It should filter out those "change" events where value was not actually changed.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Dec 14 '17 at 20:56









      Alexander LeonovAlexander Leonov

      2,9451918




      2,9451918








      • 1





        This is universal solution, which works also in the case when you perform valueChanges on multiple and dependent on each others formControls. Thanks!

        – mpro
        Nov 26 '18 at 11:26
















      • 1





        This is universal solution, which works also in the case when you perform valueChanges on multiple and dependent on each others formControls. Thanks!

        – mpro
        Nov 26 '18 at 11:26










      1




      1





      This is universal solution, which works also in the case when you perform valueChanges on multiple and dependent on each others formControls. Thanks!

      – mpro
      Nov 26 '18 at 11:26







      This is universal solution, which works also in the case when you perform valueChanges on multiple and dependent on each others formControls. Thanks!

      – mpro
      Nov 26 '18 at 11:26













      8














      Well actually, the true answer is, if you want to subscribe to any form changes and still run patchValue inside it, then you should just add the {emitEvent: false} option to patchValue, thus the patching will not trigger another change detection



      code:



      this.formGroup
      .valueChanges
      .subscribe( _ => {
      this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
      } );


      PS. This is also less tedious than subscribing to each form control one-by-one to avoid triggering change max call stack exceeded. Especially if you form has 100 controls to subscribe to.



      Now to elaborate further, if you still need to updateValueAndValidity inside the subscription, then I suggest you use the distinctUntilChanged rxjs operator, to only run the subscription, when some value changes.



      Now we will also have to make it a custom validation function, because by default, distinctUntilChanged validates objects by pointer and the pointer is new on every change.



      this.formGroup
      .valueChanges
      .distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
      .subscribe( _ => {
      this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
      this.formGroup.get( 'controlName' ).updateValueAndValidity();
      } );


      And voila, we are patching and updating, without running into the maximum call stack!






      share|improve this answer






























        8














        Well actually, the true answer is, if you want to subscribe to any form changes and still run patchValue inside it, then you should just add the {emitEvent: false} option to patchValue, thus the patching will not trigger another change detection



        code:



        this.formGroup
        .valueChanges
        .subscribe( _ => {
        this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
        } );


        PS. This is also less tedious than subscribing to each form control one-by-one to avoid triggering change max call stack exceeded. Especially if you form has 100 controls to subscribe to.



        Now to elaborate further, if you still need to updateValueAndValidity inside the subscription, then I suggest you use the distinctUntilChanged rxjs operator, to only run the subscription, when some value changes.



        Now we will also have to make it a custom validation function, because by default, distinctUntilChanged validates objects by pointer and the pointer is new on every change.



        this.formGroup
        .valueChanges
        .distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
        .subscribe( _ => {
        this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
        this.formGroup.get( 'controlName' ).updateValueAndValidity();
        } );


        And voila, we are patching and updating, without running into the maximum call stack!






        share|improve this answer




























          8












          8








          8







          Well actually, the true answer is, if you want to subscribe to any form changes and still run patchValue inside it, then you should just add the {emitEvent: false} option to patchValue, thus the patching will not trigger another change detection



          code:



          this.formGroup
          .valueChanges
          .subscribe( _ => {
          this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
          } );


          PS. This is also less tedious than subscribing to each form control one-by-one to avoid triggering change max call stack exceeded. Especially if you form has 100 controls to subscribe to.



          Now to elaborate further, if you still need to updateValueAndValidity inside the subscription, then I suggest you use the distinctUntilChanged rxjs operator, to only run the subscription, when some value changes.



          Now we will also have to make it a custom validation function, because by default, distinctUntilChanged validates objects by pointer and the pointer is new on every change.



          this.formGroup
          .valueChanges
          .distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
          .subscribe( _ => {
          this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
          this.formGroup.get( 'controlName' ).updateValueAndValidity();
          } );


          And voila, we are patching and updating, without running into the maximum call stack!






          share|improve this answer















          Well actually, the true answer is, if you want to subscribe to any form changes and still run patchValue inside it, then you should just add the {emitEvent: false} option to patchValue, thus the patching will not trigger another change detection



          code:



          this.formGroup
          .valueChanges
          .subscribe( _ => {
          this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
          } );


          PS. This is also less tedious than subscribing to each form control one-by-one to avoid triggering change max call stack exceeded. Especially if you form has 100 controls to subscribe to.



          Now to elaborate further, if you still need to updateValueAndValidity inside the subscription, then I suggest you use the distinctUntilChanged rxjs operator, to only run the subscription, when some value changes.



          Now we will also have to make it a custom validation function, because by default, distinctUntilChanged validates objects by pointer and the pointer is new on every change.



          this.formGroup
          .valueChanges
          .distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
          .subscribe( _ => {
          this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
          this.formGroup.get( 'controlName' ).updateValueAndValidity();
          } );


          And voila, we are patching and updating, without running into the maximum call stack!







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jun 9 '18 at 2:10

























          answered Jun 9 '18 at 1:56









          Karl Johan VallnerKarl Johan Vallner

          1,23411428




          1,23411428























              5














              My answer is just development of this one.



              By adding distinctUntilChanged() in the pipeline just before subscribe() you avoid the "Maximum call stack size exceeded" because




              distinctUntilChanged method only emit when the current value is different than the last.




              The usage:



              this.userForm.get('password')
              .valueChanges.pipe(distinctUntilChanged())
              .subscribe(val => {})


              Documentation






              share|improve this answer




























                5














                My answer is just development of this one.



                By adding distinctUntilChanged() in the pipeline just before subscribe() you avoid the "Maximum call stack size exceeded" because




                distinctUntilChanged method only emit when the current value is different than the last.




                The usage:



                this.userForm.get('password')
                .valueChanges.pipe(distinctUntilChanged())
                .subscribe(val => {})


                Documentation






                share|improve this answer


























                  5












                  5








                  5







                  My answer is just development of this one.



                  By adding distinctUntilChanged() in the pipeline just before subscribe() you avoid the "Maximum call stack size exceeded" because




                  distinctUntilChanged method only emit when the current value is different than the last.




                  The usage:



                  this.userForm.get('password')
                  .valueChanges.pipe(distinctUntilChanged())
                  .subscribe(val => {})


                  Documentation






                  share|improve this answer













                  My answer is just development of this one.



                  By adding distinctUntilChanged() in the pipeline just before subscribe() you avoid the "Maximum call stack size exceeded" because




                  distinctUntilChanged method only emit when the current value is different than the last.




                  The usage:



                  this.userForm.get('password')
                  .valueChanges.pipe(distinctUntilChanged())
                  .subscribe(val => {})


                  Documentation







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 27 '18 at 7:56









                  mprompro

                  1,96421021




                  1,96421021






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f47821809%2frangeerror-maximum-call-stack-size-exceeded-when-using-valuechanges-subscribe%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Tonle Sap (See)

                      I get strange results when I access the Sqlitedatabase with Unity C# via XAMPP

                      Guatemaltekische Davis-Cup-Mannschaft