I have an angular 6 application and I’m trying to do something which I don’t know is possible. It’s rather complicated so bear with me.
I have this in the template:
<div *ngIf="groupService.userGroups && groupService.userGroups.length > 0">
<div *ngFor="let invitationWatcher of invitationService.getInvitations()">
{{ invitationWatcher | json }}
</div>
</div>
Then in the component, I have this:
getInvitations() {
console.log(‘Getting invitations’);
const groupedInvitations$: Observable<any>[] = [];
this.groupService.userGroups.forEach(group => {
const groupInvites$ = this._firestoreService.getCollection$(`Invitations/${group.groupID}/Invites`); // returns Observable<any>[]
groupedInvitations$.push(groupInvites$);
});
return Observable.combineLatest(groupedInvitations$);
}
When I run this, I get the console message ‘Getting invitations’ repeatedly followed by this error:
Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
This makes sense. The function returns an observable, not an array (or something iterable). When I pipe the function call through async like this:
<div *ngFor="let invitationWatcher of invitationService.getInvitations() | async”>
The error goes away, but my browser freezes. I get the message ‘Getting invitations’ repeatedly. I have to kill the browser in order to get out of the freeze.
What we want: the function should return an observable that can be watched and eventually resolves to an array.
What’s happening: the function is being repeatedly called, causing the browser to freeze, and a new observable is returned every time.
One way around this (which I’ve tried and it works!) is to call getInvitations() from the constructor like this:
constructor(…) {
this.groupService.userGroupsChange$.subscribe(result => {
if (this.groupService.userGroups) {
this.allInvitations$ = this.getInvitations();
}
});
}
Then get the template to watch allInvitations$ instead of calling the function, like this:
<div *ngFor="let invitationWatcher of allInvitations$ | async”>
But that’s actually not an option. We want to avoid setting the invitation observable in any initialization code (we have our reasons). Instead we want to call the function directly (without errors and without browser freezing).
Is this possible?