Reputation: 33
e(1): Updated code to address typo's in original question.
e(2): Attempted to 'JSON.stringify()' the data pushed into my JSON object in 'createContent()'. No luck.
e(3): Added plnkr as requested: http://plnkr.co/edit/j024MYCQbypAGaf762fT
I have a model...
class Content {
constructor(public name: string) { }
}
I have a service...
class ContentService {
private _contents$: Subject<Content[]>
= new Subject<Content[]>();
get contents$(): Observable<Content[]> {
return this._contents$.asObservable();
}
private _data: { contents: Content[] } = { contents: [] };
...
load(): void {
createContent(new Content("Test Content..."));
}
createContent(item: Content): void {
this._data.contents.push(item);
this._contents$.next(this._data.contents);
}
}
I have a component...
@Component({
...
template: `
<h1 *ngFor="let item of contents$ | async">{{ item.name }}</h1>
`
})
class ContentListComponent {
contents$: Observable<Content[]>;
constructor(private _contentService: ContentService) { }
ngOnInit(): void {
this.contents$ = this._contentService.contents$;
this._contentService.load();
}
}
Simply put, I don't understand why the Observable in my component is not functioning correctly.
If I change these around, such that I have an array in the component, subscribe to the service 'contents$' to populate the array, then it's no biggie.
When I log the output of the service and functions called, everything is also dandy. The only symptom I am experiencing is that the "*ngFor" does not appear to be properly handling the stream. It's something obvious, isn't it?
Upvotes: 3
Views: 1516
Reputation: 657058
The problem is that Angular evaluates the
<h1 *ngFor="let item of contents$ | async">{{ item.name }}</h1>
only when change detection runs the next time.
Because
this._service.load();
is executed sync, the event is emitted before Angular had a chance to subscribe.
If you for example use a BehaviorSubject
instead of Subject
which emits that last emitted value to new subscribers, then you get the desired behavior.
You could also invoke change detection manually before calling this._service.load();
or call this._service.load();
delayed
but that depends on your specific requirements.
Upvotes: 4
Reputation: 202138
I see a potential problem in your code:
createContent(item: Content): void {
this._data.contents$.push(item);
this._contents$.next(this._data.contents$);
}
I would use the following instead:
createContent(item: Content): void {
this._data.contents.push(item); // <----
this._contents$.next(this._data.contents); // <----
}
Upvotes: 0