0

I want to be able to get access to data outside of my method with .subscribe

This is my Service which "works" fine

getSessionTracker(): Observable<ISessionTracker[]> {
    return this.http.get(this._url)
        .map((res: Response) => {
            let data = res.json();
            return data;
        })
       .catch(this.handleError)
} 

Component is where my trouble is

sessionTrackers: ISessionTracker[] = [];  //  object array 

this.trackerService.getSessionTracker()
    .subscribe((sessionTrackers: ISessionTracker[]) => {
        this.sessionTrackers = sessionTrackers;
        console.log('real data in subscribe', this.sessionTrackers[0].SessionId);
    },
    (err: any) => console.log(err),
    () => console.log('getSessionTracker()'));

// outside of function this does NOT work

 console.log('real data', this.sessionTrackers);

2 problems

  1. console.log INSIDE method with .subscribe works if I do a console.log, however with this.sessionTrackers[0].SessionId it is undefined , but this.this.sessionTrackers
  2. this data not working outside of method

How can I persist the data?

1 Answers1

5

The issue is a timing one. Since the service call is asynchronous, the data does not arrive immediately when the subscribe is called. Rather, when the response is returned from the service, the callback function defined as the argument to the subscribe method is then called.

That's why the console.log within the Subscribe works.

Here is a picture roughly outlining the order of the execution.

enter image description here

However, your code will retain the value when it is indeed retrieved.

So outside of the subscribe function, you just need to check for the existence of the value. Something like this:

if (this.sessionTrackers) { console.log(...) }

Or if you are binding to the data, you need to use *ngIf or the safe navigation operator (?).

If you are using reactive forms, then you may want to separate setting up the form model (using FormBuilder) and setting the default values.

I have an example of reactive forms here: https://github.com/DeborahK/Angular2-ReactiveForms (check out the APM folder).

ngOnInit

ngOnInit(): void {
    this.productForm = this.fb.group({
        productName: ['', [Validators.required,
                           Validators.minLength(3),
                           Validators.maxLength(50)]],
        productCode: ['', Validators.required],
        starRating: ['', NumberValidators.range(1, 5)],
        tags: this.fb.array([]),
        description: ''
    });

    // Read the product Id from the route parameter
    this.sub = this.route.params.subscribe(
        params => {
            let id = +params['id'];
            this.getProduct(id);
        }
    );
}

This code sets up the reactive form and watches for changes to the route parameters. When the route parameter is set, it calls getProduct(id).

getProduct

getProduct(id: number): void {
    this.productService.getProduct(id)
        .subscribe(
            (product: IProduct) => this.onProductRetrieved(product),
            (error: any) => this.errorMessage = <any>error
        );
}

This goes to get the data, somewhat similar to what you are doing. Notice that in the subscribe callback I'm calling another method: onProductRetrieved.

onProductRetrieved

onProductRetrieved(product: IProduct): void {
    if (this.productForm) {
        this.productForm.reset();
    }
    this.product = product;

    // Update the data on the form
    this.productForm.patchValue({
        productName: this.product.productName,
        productCode: this.product.productCode,
        starRating: this.product.starRating,
        description: this.product.description
    });
    this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
}

Here is where I am setting the default values for the reactive form since I now know I have the data. You can use setValue or patchValue for this.

DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • Hi Deb. So I have an interface in which there is a SessionId , but while inside the method I can spit out console log of sessionTrackers, but not sessionTrackers[0].SessionId that is undefined which I don't get –  Sep 09 '17 at 00:38
  • so with reactive form , I have a lot of typescript in which I want to set values from the subscribed data, so I won't be using *nfIf in the html for this - –  Sep 09 '17 at 00:39
  • I updated my answer to include how I populate my reactive forms. Hope this helps. – DeborahK Sep 09 '17 at 00:55