0

I am trying to get the information of a specific loan by it's ID and the details of items in that loan to display it in the detail page. However, I am unable to and I do not know how to retrieve the loan and loan items using the loan service's getLoanById method given to me.

detail.page.ts

export class DetailPage {
  loan: Loan;
  loanId: string;

  constructor(private route: ActivatedRoute, private loanService: LoanService) {
    this.loanId = this.route.snapshot.params.id;
    this.loan = this.loanService.getLoanById(this.loanId);
  }
}

loan.service.ts

  getLoanById(id: string) {
    return firebase.firestore().collection('loans').doc(id).get().then(doc => {
      let loan = new Loan(doc.data().username, doc.data().status, doc.data().duedate.toDate(), doc.id);

      return firebase.firestore().collection('loans/' + id + '/items').get().then(collection => {
        loan.items = []; // Empty array
        collection.forEach(doc => {
          let item = new Item(doc.id, doc.data().quantity);
          loan.items.push(item);
        })
        return loan;
      });
    });
  }
Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
kahhao39
  • 1
  • 4

2 Answers2

1

Change the getLoanById() to the following method:

 async getLoanById(id: string) : Promise<any> {
    const doc = await firebase.firestore().collection('loans').doc(id).get();
    let loan = new Loan(doc.data().username, doc.data().status, doc.data().duedate.toDate(), doc.id);
    const collection = await firebase.firestore().collection('loans/' + id + '/items').get();
    loan.items = []; // Empty array
    collection.forEach(doc_1 => {
      let item = new Item(doc_1.id, doc_1.data().quantity);
      loan.items.push(item);
    });
    return loan;
  }

Since the get() method is asynchronous, therefore use async/await to wait until the data is retrieved to then add it to the list. Then inside the DetailPage you can do the following:

   constructor(private route: ActivatedRoute, private loanService: LoanService) {
    this.loanId = this.route.snapshot.params.id;
    this.loanService.getLoanById(this.loanId).then((result){
      console.log(result);
     });
  }

The then() method returns a Promise. It takes up to two arguments: callback functions for the success and failure cases of the Promise. Once a Promise is fulfilled or rejected, the respective handler function (onFulfilled or onRejected) will be called asynchronously.

Check:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
  • The detail.page.html now loads faster than the data being retrieved from firebase causing the page to only load partially. Is there a way to fully retrieve the firebase data before loading the page? – kahhao39 Jun 24 '21 at 16:01
  • Yes the html will load before because this call is asynchronous , usually since you are using angular and ionic then just implement `OnInit` class and override the method `ngOnInit()` call `getLoanById()`. Also use the component https://ionicframework.com/docs/api/loading to show a small spinner before loading the data and dismiss it after data is loaded – Peter Haddad Jun 24 '21 at 16:09
  • I've impmeneted the OnInit class but I am unable to figure out how to override the method ngOnInit() to call getLoanById(). – kahhao39 Jun 24 '21 at 16:44
  • after implementing it, isnt it giving you an error? Just write `ngOnInit() {}` – Peter Haddad Jun 24 '21 at 16:47
  • I did write ngOnInit(){} but am I supposed to write anything in the ngOnInit method as the html is still loading first. – kahhao39 Jun 24 '21 at 16:56
  • html will also load first... but with `ngOnInit` the asychronous call will get called only once.. and when you use the loadingcontroller you can then handle what to show in the html until data is retrieved. Check this example: https://stackoverflow.com/a/38014256/7015400 – Peter Haddad Jun 24 '21 at 16:58
  • I've found that you can prevent the html components that require the firestore data from loading until you have fully retrieved the data by adding an "*ngIf=loan" to it. This checks if the loan is retrieved yet before attempting to display it in html. – kahhao39 Jun 29 '21 at 14:13
-2

To access loan and item data from Firebase, the Firestore database should be utilized. Firestore is a NoSQL database offered by Firebase which enables flexible document-based storage. Here's an easy step-by-step guide on how to achieve this: Establish Firebase in Your Project: If you haven't done so already, create and integrate Firebase into your application using its official documentation for different platforms (web, Android and iOS) as soon as possible. Design the Firestore Data Structure: Next, decide on the structure of your data in Firestore. In this instance, consider having a collection named "loans," where each document represents an individual loan with fields representing information about that loan as well as an additional sub-collection called "items" within each loan document that contains details about associated items with that loan. Add a Loan Document: In order to store information about loans, create a document in the "loans" collection. Each document will feature its own unique identifier that allows you to retrieve loan data later.

  • 1
    Using ChatGPT to post answers is not allowed. See https://meta.stackoverflow.com/questions/421831/temporary-policy-chatgpt-is-banned – Eric Aya Jul 24 '23 at 10:22