Jake
Jake

Reputation: 26117

How to access component variables in subscribe method

I am trying to show a loading spinner before a Service is called. If the service fails, it should hide the loading spinner.

I am able to show the spinner, but not able to hide it, because the component variables are not accessible in the subscribe method. Is there any way around this?

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { NgxSpinnerService } from 'ngx-spinner';
import { FoodService } from '../../../services/food.service';

import { Food } from '../../../interfaces/Food';

@Component({
  selector: 'app-food',
  templateUrl: './food.component.html',
  styleUrls: ['./food.component.css']
})
export class FoodComponent implements OnInit {

  foodContents$: Observable<Food>
  public foodPageId : any;
  public spinnerStatus: boolean = false;
  public foodRequest;

  constructor(private foodService:FoodService, private route: ActivatedRoute, private spinner: NgxSpinnerService) { 
    this.route.params.subscribe(res => this.foodPageId = res.id);
  }

  ngOnInit() {
    if(!this.foodRequest)
    {
      this.spinner.show();
      this.spinnerStatus = true;
      this.foodContents$ = this.foodService.GetFoodPageContent(this.foodPageId);
      this.foodContents$.subscribe({
        error(err) {
          /*Not able to access spinner and spinnerStatus variables.
          How to access these?*/
          this.spinner.hide();
          this.spinnerStatus = false;
        }
      }); 
    }
  }

}

Upvotes: 0

Views: 940

Answers (2)

Kamil Kiełczewski
Kamil Kiełczewski

Reputation: 92477

Handle error like this (the error handling function should be the second argument):

this.foodContents$.subscribe(()=>{},
 (err) => {
    this.spinner.hide();
    this.spinnerStatus = false;
  }
); 

If you wanna use also finnaly (try-catch-finally) you can also put third function as last argument of subscribe('onCompleted').

UPDATE

You can also try following approach (change ngOnInit() to async ngOnInit())

try {
  let result= await this.foodService.GetFoodPageContent(this.foodPageId).toPromise()
  // ... process result
}
catch(err) {  
  this.spinnerStatus = false;
} 
finally {
  this.spinner.hide();
}

Upvotes: 1

AVJT82
AVJT82

Reputation: 73357

Your this is not pointing to the correct scope.. check this: How to access the correct `this` inside a callback?

You can solve it by using arrow function:

  .subscribe({
    error: () => {
      this.spinner.hide();
      this.spinnerStatus = false;
    }
  });

With that, this is now pointing at the component, meaning you have access to your variables.

But I would do... to could call these in finalize (using rxjs 6) which is called despite error happening or success:

this.foodContents$.pipe(
  finalize(() => {
    this.spinner.hide();
    this.spinnerStatus = false;
  })
 )
  .subscribe((data: SomeModel) => {
    // success, do something with data
  },
  (err) => {
    // error, do something..
 }));

Since usually we want to do also something else when error or success happens.

Upvotes: 3

Related Questions