5
votes

I am using an observable to return a list from service to my component and in my component I am using ChangeDetectionStrategy.OnPush and in template I am using async pipe, hoping this would give some performance benefit since Change Detection isn't performed all the time but only when new contents are available.

Below is my service:

import { Injectable, Inject, EventEmitter } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class ListService {

    public _list$: Subject<any[]>;

    private list: any[] = [];

    constructor() {
        this._list$ = <Subject<any>>new Subject();
    }

    get list$() {
        return this._list$.asObservable();
    }

    loadList() {
        //if this.list is populated through an http call the view is updated, 
        //if its a static list like below, it doesn't trigger view update.
        //this.list = ['Red', 'Green', 'Yellow', 'Blue'];
        this._list$.next(this.list);
    }
}

In my component I have:

import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Observable } from 'rxjs/Observable';

@Component({
    templateUrl: `
<ul>
        <li *ngFor="let item of (list$ | async);">
            {{item}}
        </li>
    </ul>
`,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ListComponent {

    public list$: Observable<any[]>;

    constructor(
        private _ls: ListService
    ) {}

    ngOnInit() {
        this.list$ = this._ls.list$;
        this._ls.loadList();
    }
}

The issue if the loadList contents fetch list contents through an http call, the view is updated, if the list content are static, the view isn't updated.

If I wrap list update inside setTimeout, it does trigger view update

setTimeout(() => {
    this._list$.next(this.list);
}, 1);

I just started exploring Observables, can anyone please guide whats wrong with above code?

1

1 Answers

4
votes

Just move the code fron ngOnInit() to the constructor. Angular tries to resolve the binding (subscribe to the observable) before ngOnInit() is called and fails because thod._list$ is null and doesn't try later because it doesn't recognise the change.