Skip to content

Commit 45dcb64

Browse files
committed
feat(firestore): Added option to include document IDs on valueChanges()
An 'idField' string arg can be used with collection.valueChanges() to include the document ID on the emitted data payload.
1 parent b91cd5a commit 45dcb64

File tree

3 files changed

+23
-5
lines changed

3 files changed

+23
-5
lines changed

docs/firestore/collections.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ interface DocumentSnapshot {
7373

7474
There are multiple ways of streaming collection data from Firestore.
7575

76-
### `valueChanges()`
76+
### `valueChanges(idField?: string)`
7777

78-
**What is it?** - The current state of your collection. Returns an Observable of data as a synchronized array of JSON objects. All Snapshot metadata is stripped and just the method provides only the data.
78+
**What is it?** - The current state of your collection. Returns an Observable of data as a synchronized array of JSON objects. All Snapshot metadata is stripped and just the method provides only the data. Optionally, you can pass an `idField` string to include the document ID.
7979

8080
**Why would you use it?** - When you just need a list of data. No document metadata is attached to the resulting array which makes it simple to render to a view.
8181

src/firestore/collection/collection.spec.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { FirebaseApp, AngularFireModule } from '@angular/fire';
22
import { AngularFirestore } from '../firestore';
33
import { AngularFirestoreModule } from '../firestore.module';
4-
import { AngularFirestoreDocument } from '../document/document';
54
import { AngularFirestoreCollection } from './collection';
65
import { QueryFn } from '../interfaces';
76
import { Observable, BehaviorSubject, Subscription } from 'rxjs';
@@ -70,6 +69,19 @@ describe('AngularFirestoreCollection', () => {
7069

7170
});
7271

72+
it('should optionally map the doc ID to the emitted data object', async (done: any) => {
73+
const ITEMS = 1;
74+
const { ref, stocks, names } = await collectionHarness(afs, ITEMS);
75+
const idField = 'myCustomID';
76+
const sub = stocks.valueChanges(idField).subscribe(data => {
77+
sub.unsubscribe();
78+
const stock = data[0];
79+
expect(stock[idField]).toBeDefined();
80+
expect(stock).toEqual(jasmine.objectContaining(FAKE_STOCK_DATA));
81+
deleteThemAll(names, ref).then(done).catch(fail);
82+
})
83+
});
84+
7385
it('should handle multiple subscriptions (hot)', async (done: any) => {
7486
const ITEMS = 4;
7587
const { randomCollectionName, ref, stocks, names } = await collectionHarness(afs, ITEMS);

src/firestore/collection/collection.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,18 @@ export class AngularFirestoreCollection<T=DocumentData> {
104104
/**
105105
* Listen to all documents in the collection and its possible query as an Observable.
106106
*/
107-
valueChanges(): Observable<T[]> {
107+
valueChanges(idField?: string): Observable<T[]> {
108108
const fromCollectionRef$ = fromCollectionRef<T>(this.query);
109109
const scheduled$ = this.afs.scheduler.runOutsideAngular(fromCollectionRef$);
110110
return this.afs.scheduler.keepUnstableUntilFirst(scheduled$)
111111
.pipe(
112-
map(actions => actions.payload.docs.map(a => a.data()))
112+
map(actions => actions.payload.docs.map(a => {
113+
return {
114+
...a.data() as Object,
115+
...(idField ? { [idField]: a.id } : null)
116+
} as T;
117+
})
118+
)
113119
);
114120
}
115121

0 commit comments

Comments
 (0)