Ahmed Adel
Ahmed Adel

Reputation: 49

using variables from async operation in an angular template

so am trying to basically get user details after they login, but am facing issues due to request to get the details taking so long.. It breaks everything. I am not exactly sure, but I believe it's due to the variable being undefined the moment of the template being loaded... What can I do to avoid that?

onLogin() {
    if (this.loginPassword === '' || this.loginUsername === '') {
      return false;
    }
    this.loading = true;
    this.auth.login(this.loginUsername, this.loginPassword)
      .subscribe((res: any) => {
        // Store the access token in the localstorage
        localStorage.setItem('access_token', res.access_token);
        this.auth.getUserData().subscribe((ele) => {
          console.log(ele, 'ele');
        });
        this.loading = false;
        // Navigate to home page
        this.router.navigate(['/']);
      }, (err: any) => {
        // This error can be internal or invalid credentials
        // You need to customize this based on the error.status code
        this.loading = false;
        this.error = true;
      });
  }

my Login function, after it navigates to the dashboard that's when everything goes south...

  getUserData(): Observable<any> {
    return this.http.get(this.globals.baseAPIUrl + 'details', this.cf.requestOptions()).pipe(
      map(res => res)
    );
  }

The function I use to get the user details, which takes so long and messes everything up...

this.auth.getUserData().subscribe((ele) => {
      this.globals = ele;
    });

How am getting the values for the dashboard and saving them

<div class="page-title-heading">
      <div class="page-title-icon" style="height: 150px; width: 130px;">
        <img src="{{ globals.userPhoto }}" alt="Raised image" class="img-fluid rounded card-img-top-img shadow-lg"
          style="height: auto;">
      </div>
      <div>
        {{ globals.userName }}
        <div class="page-title-subheading">
          {{ globals.designation }}
        </div>
      </div>
    </div>

This is how am calling them in the HTML template

Cannot read property 'userPhoto ' of undefined

I keep getting this error though, any help would be great... Thanks in advance!

Upvotes: 0

Views: 128

Answers (1)

Chris Danna
Chris Danna

Reputation: 1264

You are navigating to the new route before the response from getUserData() is received and the value is stored in globals.

You can fix this by navigating to the home page within the subscription of getUserData

onLogin() {
    if (this.loginPassword === '' || this.loginUsername === '') {
      return false;
    }
    this.loading = true;
    this.auth.login(this.loginUsername, this.loginPassword)
      .subscribe((res: any) => {
        // Store the access token in the localstorage
        localStorage.setItem('access_token', res.access_token);
        this.auth.getUserData().subscribe((ele) => {
          console.log(ele, 'ele');
          // is this where you intend to set globals?

          this.loading = false;
          // Navigate to home page
          this.router.navigate(['/']);
        });
      }, (err: any) => {
        // This error can be internal or invalid credentials
        // You need to customize this based on the error.status code
        this.loading = false;
        this.error = true;
      });
  }

Though, I have to say that it isn't clear to me where you intend on setting globals. Also, the nested subscribes can be refactored to use switchMap instead, so that is follows the pattern:

this.auth.login(this.loginUsername, this.loginPassword)
  .pipe(
    tap(res => localStorage.setItem(...)),
    catchError(err => /* error handling */),
    switchMap(res => this.auth.getUserData())
  )
  .subscribe(ele => {
    this.loading = false;
    this.globals = ele;
    this.router.navigate(['/']);
  });  

Upvotes: 2

Related Questions