Using AsyncPipe programmatically - Angular 2

Viewed 1902

I'm using a component to render table like data, I give it the list of columns, the data, how does the data map to each column, and finally a list of pipes to apply to each column data.

So far so good, only problem is when one of those pipes is the async pipe...

After experimenting for some while, I found out that when the asyncpipe is used on the template the transform method gets called several times. However if I use it programmatically the transform method gets called just once (the time I invoke it).

I guess the reason it's called multiple times on template it's because it's an impure pipe, but how can I handle it programmatically?

Here's a plunker demonstrating what I just said:

@Injectable()
export class AsyncProvider {
  constructor() {}
  
  getById(id: number) {
    // Just some mock data
    return Observable.of({id, times_five: id*5}).delay(1000);
  }
}

@Component({
  selector: 'my-app',
  providers: [AsyncPipe, AsyncProvider]
  template: `
    <div>
      <p>Template async pipe</p>
      <p>{{ asyncObj | async | json }}</p>
      <hr>
      <p>Programmatically async pipe</p>
      <p>{{ asyncObjPiped | json }}</p>
    </div>
  `,
  directives: []
})
export class App {
  constructor(
    private _provider: AsyncProvider,
    private _async: AsyncPipe
  ) {
    this.asyncObj = this._provider.getById(123);
    this.asyncObjPiped = this._async.transform(this.asyncObj);
  }
}

EDIT: Because AsyncPipe performs a markForCheck() on a ChangeDetectorRef uppon receiving new values, I also tried the following:

export class App {
  constructor(
    private _provider: AsyncProvider,
    private _async: AsyncPipe,
    private _ref: ChangeDetectorRef,
  ) {
    this.asyncObj = this._provider.getById(123);
    this.asyncObjPiped = this._async.transform(this.asyncObj);
    
    setInterval(() => {
      this._ref.detectChanges();
    }, 1000);
  }
}

Without any success :(

1 Answers
Related