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 :(