'AngularFire valueChanges with idField and non-existent document

If I call valueChanges on a Firestore document that doesn't exist, it returns undefined:

this.afs.doc('bad_document_ref').valueChanges().subscribe(snapshot => {
    console.log(snapshot) // undefined
});

But if I call valueChanges on the same bad ref, but I pass in the idField parameter, it returns an object with just the id:

this.afs.doc('bad_document_ref').valueChanges({ idField: 'custom_doc_id' }).subscribe(snapshot => {
    console.log(snapshot) // { custom_doc_id: 'bad_document_ref' }
});


I would like for the two above examples to return the same thing. I can do this by adding a pipe:

this.afs.doc('bad_document_ref').valueChanges({ idField: 'custom_doc_id' })
    .pipe(map(snapshot => {
        if(!snapshot) return undefined;
        if (Object.keys(snapshot).length === 1 && Object.keys(snapshot)[0] === 'custom_id_field') {
            return undefined;
        }
        return snapshot;
    }))
    .subscribe(snapshot => {

    console.log(snapshot) // undefined

});

Is there a reason why the first two examples don't return the same thing? It seems like the logical thing to do, for the sake of consistency. Maybe there is a reason I'm not thinking of for why they would return different values?



Solution 1:[1]

The valueChange() method is basically the current state of your collection. You can listen for changes on the collection’s documents by calling valueChanges() on the collection reference. It returns an Observable of data as a synchronized array of JSON objects. All Snapshot metadata is stripped and just the document data is included.

When you pass an option object with an idField key containing a string like .valueChanges({ idField: 'propertyId' }); , it returns JSON objects with their document ID mapped to a property with the name provided by idField.

When the document doesn't actually exist, you would expect it to return nothing. In the first piece of code, you are not providing idField and the document doesn't exist, the observable returned undefined, which is justified. However, when you specify idField in the second piece of code, you basically say that when you return the data, you want the id of the document to be added to it. However if there is no data, there should not be any value returned, which is what you wanted to point out and which is quite justified. In other words, if the document does not exist, ideally it should return undefined even if you specify the idField parameter.

A GitHub link pointing towards the same issue says that the appropriate behavior is addressed in version 7 api.

Another GitHub link to be followed on this.

Solution 2:[2]

I am using: angularFirestore.collection<Item>('items');

Note that for the object mapped I use <Item>, so maybe you can use it in your doc.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2