3
votes

Variables inside subscribe are undefined but when I put breakpoint before hitting service subscribe I have the variable defined.

In Service:

getCashierRiskProfiles(): Observable<ICashierRiskProfile[]> {
  return this.http.get(this._baseUrl + "src/HTTPJson/cashierriskprofile.json")
    .map((res: Response) => res.json())
    .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}

In Component:

import { Component, OnInit } from "@angular/core";
import { Observable } from 'rxjs/Observable';

import { CashierRiskProfileService } from "./cashierriskprofile.service";
import { ICashierRiskProfile } from "../shared/interfaces";

@Component({
  selector: "cashierriskprofile",
  templateUrl: "../src/app/cashierriskprofile/cashierriskprofile.component.html"
})
export class CashierRiskProfileComponent implements OnInit {
  filterText: string;
  cashierRiskProfiles: ICashierRiskProfile[];

  constructor(
    private sorter: Sorter,
    private service: CashierRiskProfileService
  ) { }

  ngOnInit() {
    this.filterText = "Filter Exceptions:";
    //// Observable technique
    this.service.getCashierRiskProfiles()
      .subscribe(
        (riskProfiles) => {
          this.cashierRiskProfiles = riskProfiles;
          this.filterText = "Inside Subscribe:";
        },
        err => {
          // Log errors if any
          console.log(err);
        }
      );
  }
}

In above component code inside ngonInit() service call, this.cashierRiskProfiles inside the subscribe is undefined, but after I put breakpoint before the service callI have that variable available and defined.

I have seen lot of people having this issue with component variables with this.variablename getting undefined inside subscribe. When you notice this.filterText I can get the values assigned to it outside dataservice call, but when I put breakpoint inside subscribe, this.filterText is undefined and I don't know how I am losing it.

What's going on?

3
It has to do with scope. One thing you can do is pass the result (riskProfiles) to a private method and handle any logic you need to there. Something like .subscribe((riskProfiles) => this.methodToProcessResponse(riskProfiles)). Then do whatever you need to do in the methodToProcessResponse() method. - Dave V
@DaveV thanks, but is it necessary to do all that extra work to add a method to assign data to a variable ?, it used to work just fine until after I updated angular and rxjs version it started breaking. That's the only workaround to add an extra method or is there any actual fix that we can do in the code to make that variable available inside the subscribe. - VR1256
@DaveV Even after I tried by putting in that method u metioned, I still see data not getting bound to my UI, it not waiting until the object is available to bind to UI, like promises wait until the object is available and then bind to UI, observables not working properly and component variables are not accessible inside subscribe. - VR1256
Did you find any solution for this @VijenderReddyChintalapudi - Anshul Dahiya
@Anshul I put console.log inside subscribe to see the values instead of putting breakpoint and debug - VR1256

3 Answers

6
votes

I guess it's because during runtime this inside subscribe is SafeSubscribe, not your component.

use closure to call component method, like this:

populateCashierRiskProfiles() {
    const that = this;
    //// Observable technique
    this.service.getCashierRiskProfiles()
        .subscribe((riskProfiles) => {
            that.cashierRiskProfiles = riskProfiles
        });
}
0
votes

Try passing your local variable into the function as follows:

ngOnInit() {
    this.populateCashierRiskProfiles(this.cashierRiskProfiles);
}

populateCashierRiskProfiles(crp: ICashierRiskProfile[]) {
    //// Observable technique
    this.service.getCashierRiskProfiles()
        .subscribe((riskProfiles) => {
            crp = riskProfiles
        });
}

Your cashierRiskProfiles should now be populated with the updated riskProfiles.

-1
votes

Your code looks good to me. I'm following the same approach in my project and working fine for me

anyways you can try the following and let me know if it works fine

ngOnInit() {
    this.filterText = "Filter Exceptions:";
    this.populateCashierRiskProfiles();
}

populateCashierRiskProfiles() {
    //// Observable technique
    this.service.getCashierRiskProfiles()
        .subscribe((riskProfiles) => {
            this.cashierRiskProfiles = riskProfiles
        });

}