prolina
prolina

Reputation: 325

Why variable is not being updated?

I use firebase and angular 2+. In my app I have a login page. When I click 'sign in' button, the spinner is loading and after success, it should be false, but it doesn't update. Why?

Template

<div class="sign-in-form-buttons-section">
  <div>{{isLoadingInProgress}}</div>
  <button
    *ngIf="!isLoadingInProgress; else loading"
    mat-raised-button
    color="primary"
    (click)="onSignInClicked()"
  >
    Sign In
  </button>
  <ng-template #loading>
    <mat-spinner></mat-spinner>
  </ng-template>
</div>

Controller

public signInFormGroup: FormGroup;
public isLoadingInProgress: boolean = false;

constructor() {
  this.signInFormGroup = new FormGroup({
    email: new FormControl(''),
    password: new FormControl(''),
  });
}

public onSignInClicked(): void {
  this.isLoadingInProgress = true;

  const signInInfo: SignInInfo = {
    email: this.signInFormGroup.value.email,
    password: this.signInFormGroup.value.password
  };

  this.authService.signInWithEmailAndPassword(
    signInInfo.email,
    signInInfo.password,
  )
  .then(() => {
    this.isLoadingInProgress = false;
  })
  .catch(error => {
    this.snackBarService.showSnackBar(error.message);
    this.isLoadingInProgress = false;
  });
}

Upvotes: 0

Views: 126

Answers (2)

TusharKanjariya
TusharKanjariya

Reputation: 21

Yes, It happens because Angular Doesn't check every non-local variable for performance issues. For Http request, angular can't detect in one Process/Thread.

Solution: You can use the RxJS BehaviorSubject method.

For Example:

  • You can try with these below-mentioned files.

loader.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class LoaderService {
  public status: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

  display(value: boolean) {
  console.log('LoaderService.display ' + value);
  this.status.next(value);
  }
}

loader.component.ts

import {Component, OnInit} from '@angular/core';
import {LoaderService} from './loader.service';

@Component({
    selector: 'app-loader',
    templateUrl: 'loader.component.html',
    providers: [LoaderService]
})

export class LoaderComponent implements OnInit {
    isLoading: boolean;

    constructor(private loaderService: LoaderService) {
    }

    ngOnInit() {
        this.loaderService.status.subscribe((val: boolean) => {
            this.isLoading = val;          // <--- Important Block
        });
    }

    submitData() {
        this.loader.display(true);      // <--- Loader true,BehaviorSubject True.
        this.http
          .post("http://localhost:3000/login", this.loginForm.value).then(data => {
            this.loader.display(false);
          })
          .catch(err => {
                console.log(err);
                this.loader.display(false); // <--- Loader Flase,BehaviorSubject False.
          });
          this.loader.display(false);
    }
}

loader.component.html

<div class="loader" *ngIf="isLoading"></div>

It worked for me as well as many angular developers use BehaviorSubject this way.I hope it will help you.

Upvotes: 1

Barremian
Barremian

Reputation: 31115

From Promise.prototype.then() docs:

If one or both arguments are omitted or are provided non-functions, then then will be missing the handler(s), but will not generate any errors.

Try passing an argument to the then callback function.

this.authService.signInWithEmailAndPassword(
  signInInfo.email,
  signInInfo.password,
)
.then((response) => {                   // <-- `response` argument
  this.isLoadingInProgress = false;
})
.catch(error => {
  this.snackBarService.showSnackBar(error.message);
  this.isLoadingInProgress = false;
});

Upvotes: 0

Related Questions