6
votes

I'm trying to assign the data collected from a firestore document to a variable with an Observable type initialised before the constructor.

I've got the data from the collection by passing in a dynamic invoiceId string to the .doc() search, and I can assign the data to a local variable (shown below), but when trying to assign it to this.invoice, I get the following error:

Uncaught (in promise): TypeError: Cannot set property 'invoice' of undefined

-

Component:

import { Component, OnInit, Input } from '@angular/core';

import { ActivatedRoute } from '@angular/router';

import { Observable } from 'rxjs/Observable';

import { AngularFireDatabase } from 'angularfire2/database';

import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';

import { AuthService } from '../../services/auth.service';

import { Invoice } from '../invoiceModel';

@Component({
  selector: 'app-view-invoice',
  templateUrl: './view-invoice.component.html',
  styleUrls: ['./view-invoice.component.scss']
})

export class ViewInvoiceComponent implements OnInit {

  userId: string;

  invoiceId: any;

  invoicesCollection: AngularFirestoreCollection<Invoice>;
  invoices: Observable<Invoice[]>;

  invoice: Observable<Invoice>;

  constructor(private authService: AuthService, private db: AngularFirestore, private route: ActivatedRoute) {
      this.userId = this.authService.user.uid;

      this.route.params.subscribe(params => {
        this.invoiceId = params.id;
      })

      this.invoicesCollection = this.db.collection('/invoices');

      this.invoices = this.invoicesCollection.snapshotChanges().map(changes => {
          return changes.map(a => {
            const data = a.payload.doc.data() as Invoice;
            data.id = a.payload.doc.id;
            return data;
          })
      })
  }

  ngOnInit() {
    this.getInvoice();
  }

  getInvoice() {
    var docref = this.db.collection('/users').doc(this.authService.user.uid).collection('/invoices').doc(this.invoiceId);
    docref.ref.get()
        .then(function(doc) {
            if (doc.exists) {
                var invoice = doc.data(); <------WORKS
                // this.invoice = doc.data(); <------DOESN'T WORK
                console.log('Invoice data: ', doc.data());
            } else {
                console.error('No matching invoice found');
            }
    })
  }

}
3
Try creating a shallow reference of this. as in getInvoice() { const _that=this; and then within doc.exists try _that.invoice = doc.data()Guruprasad J Rao
Just tried that but it means this.invoice still doesn't get the data, I need the data to be made available anywhere in the component, not just in this functionnick.cook
Yes.. Probably. because scope of this would not be actually Component since it is within a promise. That's my guess.. So you are able to set it with _that?Guruprasad J Rao
Yes, I can set it with that, but it needs to be accessible data anywhere in the scope of the componentnick.cook
Yes.. That will be possible. But only in certain places, you won't be having access to the scope with this. But the changes you make with _that actually affects the original variable.. :)Guruprasad J Rao

3 Answers

1
votes

I was fighting the same thing. It was driving me crazy!! I'm a newbie, but I appear to have solved your issue by changing one line of code:

.then(function(doc) {   //changed from
.then((doc) => {        //changed to (removed the function)

I don't even understand the ramifications of doing so, but the scope is now working to assign the value of the variable.

1
votes

If you are using AngularFire you can do:

invoiceCol: AngularFirestoreCollection<Invoice>;
invoiceObservableArray: Observable<Invoice[]>;
invoiceArray: Invoice[];

constructor(private db: AngularFirestore) { } //--injection

getAllInvoice() { //getting data of DB
    this.invoiceCol= this.db.collection('yourInvoiceDbPath');
    return this.invoiceCol.valueChanges();
}

this.invoiceObservableArray.getAllInvoice();//calling method above

this.invoiceObservableArray.subscribe(invoice=> { //converting oberv in array
      this.invoiceArray = invoice;
    });

console.log(this.invoiceArray); //showing in console
0
votes
getInvoice() {

let _this = this; <---***

    var docref = this.db.collection('/users').doc(this.authService.user.uid)
                     .collection('/invoices').doc(this.invoiceId);
    docref.ref.get()
        .then(function(doc) {
            if (doc.exists) {
                var invoice = doc.data(); <------WORKS
                // this.invoice = doc.data(); <------WORKS
                console.log('Invoice data: ', doc.data());
            } else {
                console.error('No matching invoice found');
            }
    })
  }