#Fetching data from Firebase using Angular Signals
15 messages · Page 1 of 1 (latest)
Without knowing the specifics of the mechanism from Firebase - what I would suggest is you can setup a signal that will represent the updates from firebase, and feed the next value of that from whatever mechanism that firebase has for updating it.
Call toSignal() on the observable returned by AngularFire when you fetch data.
Thanks this is currently how I did it but is still came out as Observable
I'm currently working on an Angular 16 project and using Firebase version 9 for my backend. I'm trying to retrieve data from Firestore and have it returned as an Observable stream in the form of a Signal. However, I'm facing some difficulties with the implementation.
Here's what I have so far:
` profile_user_uid = signal<string | null>(null); // getting the ID as a signal
profile_user$ = toSignal( // trying to convert back to signal
toObservable(this.profile_user_uid).pipe(
tap((uid) => console.log('uid', uid)), // this shows the UID
map((uid) => {
if (uid) {
const user = docData<_User>(
doc(this.firestore, 'users', uid) as DocumentReference<_User>,
{
idField: 'uid',
}
);
console.log('user', user); // user Observable {source: Observable, operator: ƒ}
return user;
} else {
return null;
}
})
)
);`
HTML template:
<!-- async pipe included to show data else it will be as [Object Object] which is not the result wanted since the plan to convert it to signal is to avoid using async pipe --> {{ profile_service.profile_user$() | async | json }}
I'm struggling to figure out how to convert the Firestore snapshot into a Signal so that I can easily subscribe to it in my Angular components. I have been using Observables in my project, but I'm not sure how to handle Signals in this context.
Can someone guide me on how to properly retrieve Firestore data as a Signal in Angular 16 using Firebase version 9? Any help or code examples would be greatly appreciated. Thank you!
from my stack-overflow question: https://stackoverflow.com/questions/76383716/trying-to-get-firebase-version-9-firestore-data-as-a-signal-in-angular-version-1
toObservable(this.profile_user_uid) is an Observable<string>. The map operator takes a function A -> B and is used to transform an Observable<A> into an Observable<B>. You pass it a function that transforms the string (that is the A) into an Observable<User> (that is the B). So you end up with an Observable<Observable<User>>. And transforming it into a signal thus gives you a Signal<Observable<User>>. You must not use map(), but one of the flattening operators: switchMap, mergeMap or concatMap(). In this case, since you probably don't care about the previous user anymore when the user ID changes, use switchMap.
Hey @hexed flax thanks I did that before but it still require me to return it as Observable. But after your suggestion I tried it with a slight change. It's ugly but it works 😅
switchMap((uid) => { if (uid) { const user = docData<_User>( doc(this.firestore, 'users', uid) as DocumentReference<_User>, { idField: 'uid', } ); return from(user); } else { return from(of(null)); } })
you don't need those from() IIRC. switchMap allows you to return a Promise from the function.
Oh, an docData is already an Observable anyway.
hmmm it still returns as Observale tho... which requires the async pipe wtihout the from()
Don't use from. of(null) is an observable. user is an observable too.
Ahhh yes I see now its prettier haha
switchMap((uid) => { if (uid) { const user = docData<_User>( doc(this.firestore, 'users', uid) as DocumentReference<_User>, { idField: 'uid', } ); return user; } else { return of(null); } })
It would be even prettier this way:
private readonly userCollection: CollectionReference<User>;
constructor(private firestore: Firestore) {
this.userCollection = collection(firestore, 'user') as CollectionReference<User>;
}
// ...
switchMap(uid => uid ? docData(doc(this.userCollection, uid), { idField: 'uid' }) : of(null))
Oh yeah, it is! Thanks, @hexed flax. Wanna add it as an answer to my stackoverflow question so I can mark it as answered?
No, I don't use stackoverflow anymore.