Search code examples
angulartypescriptrxjsangular-servicesangular-changedetection

Getting result only when click submit for second time


I'm trying to do change password feature in angular 7,

from the backend side, if the current password not correct, it will return true.

and in angular side error message will appear.

but the problem is i have to click twice to show the error message, even i can see the response in logs printing true value, but not sure why the *ngIf not working

Template side

    <span *ngIf="hasError">
         wrong current password value  
    </span>

my component side

hasError: boolean;

 submit () {
     this.apiService
    .changePassword(this.formGroup.value).subscribe(res => {
  console.log(res);
  this.hasError = res;    });

service side

  changePassword(body: any){
     return this.http.post<any>(this.url + 'changePassword', body);
  }

can someone explain why i have to click submit button twice to show the html element

thanks


Solution

  • I suspect you have passed changeDetection: ChangeDetectionStrategy.OnPush in the component decorator. In this case, the angular will not read the changes until the next change detection cycle which in your case occurs on the second click.

    In order to fix this, you need to inject ChangeDetectorRef in the constructor and call the change detection cycle manually. Something like:

      constructor(private cdr: ChangeDetectorRef) {}
      
      hasError: boolean;
    
      submit () {
         this.apiService
        .changePassword(this.formGroup.value)
        .subscribe(res => {
           console.log(res);
           this.hasError = res;    
           this.cdr.markForCheck();  // <<<---- detect changes
      });
    

    Though there is no harm in using ChangeDetectorRef, another way to fix this problem is by using observables and angular async pipe.

      hasError$: new Subject();
    
      submit () {
        this.apiService
        .changePassword(this.formGroup.value)
        .subscribe(res => this.hasError$.next(res));
    

    in template:

      <span *ngIf="hasError$ | async">
           wrong current password value  
      </span>