Muirik
Muirik

Reputation: 6289

Async Pipe Not Handling Subscription as Expected in Angular 2 App

I have been successfully using Observables throughout my Angular app. Up until now I've been explicitly subscribing in the component, and then using *ngFor to iterate over an array of records in the view. Now I'd like to simplify things by using Angular's async pipe in the various views - so that will handle subscription and un-subscription. So far this isn't working.

This is what I originally had (where I was subscribing in the component):

ngOnInit() {
    this.clientService.getAll(1, this.pagesize)
        .subscribe(resRecordsData => {
            this.records = resRecordsData;
            console.log(this.records);
        },
        responseRecordsError => this.errorMsg = responseRecordsError);
}

And then in the view I was doing the following:

<tr *ngFor="let record of records.data>

By the way, the data structure from the API looks like this (the records I am iterating over are within the "data" array, hence "records.data" in the *ngFor above):

{
  "count": 15298,
  "data": [
    {

So, to move to using the async pipe, I changed my component ngOnInit call to this, where I'm explicitly declaring this to be an observable, and assigning it to a variable "records":

ngOnInit() {
    const records: Observable<any> = this.clientsService.getAll(1, this.pagesize);
    console.log(this.records);
}

I also brought the observable import from RxJs into the component, like so:

import { Observable } from 'rxjs/Observable';

And then in the view I added the async pipe, like so:

<tr *ngFor="let record of records.data | async">

As I mentioned this isn't working. I'm not getting any console errors, I just don't see any data populated to the view. Also, in the console, "records" is an empty array.

By the way, my service "getAll" call looks like this:

getAll(page, pagesize) {
    return this.http.get
    (`https://api.someurl.com/${this.ver}/clients?apikey=${this.key}&page=${page}&pagesize=${pagesize}`)
        .map((response: Response) => response.json())
        .catch(this.errorHandler);
}
    errorHandler(error: Response) {
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');
}

I'm not sure what else is necessary to get the results to populate via subscription through the async pipe here. Any ideas what's missing or in error with my code here?

Upvotes: 3

Views: 5728

Answers (2)

dbandstra
dbandstra

Reputation: 1314

records$: Observable<any>;

ngOnInit() {
  this.records$ = this.clientService.getAll(1, this.pagesize);
}

in the view (assuming you are using Angular 4+):

<table *ngIf="records$ | async as records">
  <tr *ngFor="let record of records.data">

Upvotes: 6

eko
eko

Reputation: 40647

const records is a local variable. You need to make it a field in order for template to have access to this variable.

Ex:

public records: any;
ngOnInit() {
    this.records = this.clientsService.getAll(1, this.pagesize);
    console.log(this.records);
}

Upvotes: 4

Related Questions