#Fetching data from Firebase using Angular Signals

15 messages · Page 1 of 1 (latest)

quiet flint
#

Is it possible to fetch data from Firebase using Angular Signals in an Angular application? If so, what is the recommended approach or best practice for implementing this functionality?

crisp sundial
#

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.

hexed flax
#

Call toSignal() on the observable returned by AngularFire when you fetch data.

quiet flint
#

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

hexed flax
#

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.

quiet flint
#

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)); } })

hexed flax
#

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.

quiet flint
#

hmmm it still returns as Observale tho... which requires the async pipe wtihout the from()

hexed flax
#

Don't use from. of(null) is an observable. user is an observable too.

quiet flint
#

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); } })

hexed flax
#

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))
quiet flint
#

Oh yeah, it is! Thanks, @hexed flax. Wanna add it as an answer to my stackoverflow question so I can mark it as answered?

hexed flax
#

No, I don't use stackoverflow anymore.