3
votes

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?

2

2 Answers

6
votes
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">
4
votes

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);
}