Using Angular 14 and AngularFire 7.4.1, I made an observer for a Firestore collection. It works great:
interface Scientist {
name?: string | null,
born?: number | null,
accomplishment?: string | null
};
scientist$: Observable<Scientist[]>;
constructor(public firestore: Firestore) {
this.scientist$ = collectionData(collection(firestore, 'scientists'));
}
The collection displays in the HTML view.
I see in the Firestore documentation that it’s also possible to observe a single document. I’m a big fan of Charles Babbage so I want to observe this document:
interface Scientist {
name?: string | null,
born?: number | null,
accomplishment?: string | null
};
scientist$: Observable<Scientist[]>;
charle$: Observable<Scientist>;
constructor(public firestore: Firestore) {
this.scientist$ = collectionData(collection(firestore, 'scientists')); // works
this.charle$ = onSnapshot(doc(firestore, 'scientists', 'Charles Babbage')); // doesn't work
}
That throws an error:
Type 'Unsubscribe' is not assignable to type 'Observable<Scientist>'.
Oh yeah, Firestore returns my data wrapped in a document. Let’s change the data type to any
:
charle$: Observable<any>;
That throws the same error. There seems to be something incompatible between Angular’s Observable
and Firestore’s onSnapshot
. Is there a AngularFire single document observer, e.g., documentData(doc(firestore, 'scientists', 'Charles Babbage')
?
I have a second, related question. How do I detach the collection listener?
2
Answers
Here is the code based on Dharmaraj's answer.
This makes two observers, a collection listener and a document listener. The document listener can be detached.
The
onSnapshot()
returns a function that can been called to detach the listener. It also takes a function as second param that’ll trigger every time an update is received. Try refactoring the code as shown below:You can then update the state from the function itself. Just call the
unsub();
and the listener will be detached.