How to loop through (forEach) on an Observable which has been subscribed by the template
Solution 1
You will need to manually get the result of Observable in a variable in you component.
constructor(
public fb: FirebaseProvider,
) {
this.group = this.navParams.get('group');
this.fb.getContactsByGroup(this.group.id).subscribe(list =>
this.contactsList = list);
}
and change your template to render only when the contactList
is available. And iterate over the the list.
<ng-container *ngIf="contactsList">
<single-contact-list-item
[contactId]="contact.id"
(goToModalEvent)="onGoToModal($event)"
*ngFor="let contact of contactsList">
</single-contact-list-item>
<ng-container>
By doing this your function sendSms
will work as it is and will get the list of conatcts.
public sendSMS(): void {
this.contactsList.forEach(contact => {
console.log(contact.number); // WORKING!!!!
})
//this.deviceProvider.sendSMS(this.contactsList, this.message);
}
Solution 2
You need to subscribe to an Observable
first to access data stream, then do loop. Try
public sendSMS(): void {
this.contactsList.subscribe(lists=>{
lists.forEach(contact=>{
console.log(contact.number);
}
}
}
Solution 3
You can reuse your observable containing your array and perform some operations to your stream in order to pull out the interesting data. If it is just for side effects related to your data, you can use a tap operator and do your forEach inside.
public sendSMS(): void {
this.contactsList.pipe(
tap(contactArray => {
contactArray.forEach(contact => {
// Do side effect operations with your array
});
}),
// execute only once and complete the observable
take(1)
).subscribe();
}
this.deviceProvider.sendSMS(this.contactsList, this.message);
Related videos on Youtube
rhysclay
Updated on June 04, 2022Comments
-
rhysclay almost 2 years
I have an AFS observable which I can show in my frontend like this:
constructor( public fb: FirebaseProvider, ) { this.group = this.navParams.get('group'); this.contactsList = this.fb.getContactsByGroup(this.group.id); }
My fb service:
getContactsByGroup(groupId: string):Observable<Contact[]> { return this.afs.collection<Contact>(`groups/${groupId}/contacts`).valueChanges(); }
Then my template:
<single-contact-list-item [contactId]="contact.id" (goToModalEvent)="onGoToModal($event)" *ngFor="let contact of contactsList | async"> </single-contact-list-item>
Now I have a textarea which when submitted triggers an event. What I want to do is loop through each item in the Observable (contactsList) and get a property, for example:
public sendSMS(): void { this.contactsList.forEach(contact => { console.log(contact.number); // nothing! }) //this.deviceProvider.sendSMS(this.contactsList, this.message); }
I feel like the issue is that by using the async pipe in the template the Observable is already subscribed. Any help appreciated.
-
Naman Kheterpal about 6 yearsNOT a good approach. This would make a second subscriber in memory. For every change 2 functions would be called.
-
rhysclay about 6 yearsI like this answer because I dont need to refetch the observable :) Thank you