1
votes

I'm trying to create a new document within an 'invoices' collection, which works fine on its own, and I'm also trying to add an 'items' sub-collection within this new document at the same time, which also works fine on its own.

However, when I try to do both at the same time, only the items collection appears within the new document in the firestore console, which is even stranger given I can access the details of the document in a 'view-invoice' component of the app, which doesn't display the items.

I've tried to do this by getting the reference of the new document that will be created, and then setting this new sub-collection with reference to the new document id/reference that's generated, which seems to work, but again, trying both at the same time doesn't populate the document with the main data and sub-collection.

I also tried to put the method to add the sub-collection within the then() method of the initial document creation to get around the potential asynchronous issue causing this, but that produced the same result, only adding the sub-collection.

Component:

save() {

    let _this = this;

    let invoiceSubtotal = 0;
    let invoiceTax = 0;
    let invoiceTotal = 0;

    for (let item of this.items) {
        invoiceSubtotal += item.subtotal;
        invoiceTax += item.tax;
        invoiceTotal += item.total;
    }

    this.invoice = {
        id: null,
        invoiceId: 999,
        reference: this.newInvoiceForm.get('reference').value,
        date: new Date(this.newInvoiceForm.get('date').value),
        contact: this.selectedContact,
        description: this.newInvoiceForm.get('reference').value,
        subtotal: +invoiceSubtotal,
        tax: +invoiceTax,
        total: +invoiceTotal,
        paid: false
    }

    this.db.collection('/users').doc(this.userId).collection('/invoices').add(this.invoice)
        .then(function(docRef) {
            _this.notifService.showNotification('New invoice created', null);
        })
        .catch(function(error) {
            _this.notifService.showNotification('Error creating invoice: ' + error.message, null);
        })

    let ref = _this.db.collection('/users').doc(_this.userId).collection('/invoices').ref.doc().id;
    console.log('ref: ' + ref);

    for (let item of _this.items) {
        _this.db.collection('/users').doc(_this.userId).collection('/invoices').doc(ref).collection('/items').add(item)
            .then(function(docRef) {
                console.log('document added to items collection: ', item);
            })
            .catch(function(error) {
                console.error('Error adding document to items collection: ' + error.message);
            })

    }

}
2

2 Answers

0
votes

I've solved this by using a different method to set the document data.

Rather than adding the document directly using the collection().add() method, I've used the 'ref' variable that I got to set the sub-collection as a parameter for doc(ref).set(this.invoice), so that this absolutely references the same document reference that the items sub-collection has items pushed to lower down.

let ref = _this.db.collection('/users').doc(_this.userId).collection('/invoices').ref.doc().id;
    console.log('ref: ' + ref);

    this.db.collection('/users').doc(this.userId).collection('/invoices').doc(ref).set(this.invoice)
        .then(function(docRef) {
            _this.notifService.showNotification('New invoice created', null);
        })
        .catch(function(error) {
            _this.notifService.showNotification('Error creating invoice: ' + error.message, null);
        })

    for (let item of _this.items) {
        _this.db.collection('/users').doc(_this.userId).collection('/invoices').doc(ref).collection('/items').add(item)
            .then(function(docRef) {
                console.log('document added to items collection: ', item);
            })
            .catch(function(error) {
                console.error('Error adding document to items collection: ' + error.message);
            })

    }
0
votes

It's an old question but this is for the viewer's reference. Using firestore Batch will be a better idea to do this. Create a batch and add the main document followed by the subcollection document(s).