kenruizinoue
kenruizinoue

Reputation: 117

Angular: Parsing fetched data from firebase with 2 deep level

I'm trying to parse fetched data from firebase at Angular (Typescript).

My JSON data looks like this in firebase:

"customer" : {
  "customerId1" : {
    "documents" : {
      "documentId1" : {
        "documentName" : "file1.pdf",
        "documentUrl" : "someUrl1"
      },
      "documentId2" : {
        "documentName" : "file2.pdf",
        "documentUrl" : "someUrl2"
      }
    },
    "email" : "[email protected]",
    "name" : "Customer 1",
  },
  "customerId2" : {
    "documents" : {
      "documentId3" : {
        "documentName" : "file3.pdf",
        "documentUrl" : "someUrl3"
      },
      "documentId4" : {
        "documentName" : "file4.pdf",
        "documentUrl" : "someUrl4"
      }
    },
    "email" : "[email protected]",
    "name" : "Customer 2",
  }
}

As you can see, each customer has 3 properties, documents, email and name at the first level. At the second level, the document property has nested property documentName and documentUrl. And for parsing customer data I used the following code.

customer.component.ts:

...
export class CustomerComponent implements OnInit {

  customerObservable: Observable<any[]>;
  customerList: Customer[];

  constructor(db: AngularFireDatabase) {
    // Listen to customer data
    this.customerObservable.subscribe(data => {
      this.customerList = data;
    });
  }

}
...

With this code I can fetch and iterate data with the ngFor directive at html with customerList variable. The question is, how can I achieve something like this?

// Variable that contains array of an array of customer's document array
documentList: Document[][];
// Or this
// Variable that holds customer's documents
customerDocuments: Document[];

// Where Document model looks like this
export class Document {
    public documentName: string;
    public documentUrl: string;
}

Thank you for the support.

Upvotes: 1

Views: 1753

Answers (1)

Arttu
Arttu

Reputation: 371

Here is the service code:

import {Injectable} from '@angular/core';
import {AngularFireDatabase} from 'angularfire2/database';   
//rxJS
import {Observable} from 'rxjs/Observable';
import 'rxjs/operator/switchMap';   

@Injectable()
export class FirebaseService {
  constructor(private angularFireDatabase: AngularFireDatabase) {}

  onGetUserDocuments(customer: string) {
    return this.angularFireDatabase.list(`customer/${customer}/documents`).valueChanges()
  }

  onGetUsersDocuments(){
    return this.angularFireDatabase.list('customer').snapshotChanges()
      .map((changes)=>{
        return changes.map((data) => {
          return data.payload.key
        });
      })
      .switchMap((usersId: string[]) => {
        return Observable.combineLatest( usersId.map((u)=>{
          return this.onGetUserDocuments(u);
        }))
      })
  }
}

Then in your component you can call:

import {Component, OnInit} from '@angular/core'; 
import {FirebaseService} from '../services/firebase.service';
@Component({
  selector: 'new',
  templateUrl: './new.component.html',
  styleUrls: ['./new.component.css']
})
export class NewComponent implements OnInit {
  constructor(private firebaseService: FirebaseService) {}

  ngOnInit(){
    this.firebaseService.onGetUsersDocuments().subscribe(data => console.log(data));
  }
}

That will give you:

[Array(2), Array(2)]
0: Array(2)
  0: {documentName: "file1.pdf", documentUrl: "someUrl1"}
  1: {documentName: "file2.pdf", documentUrl: "someUrl2"}
1: Array(2)
  0: {documentName: "file3.pdf", documentUrl: "someUrl3"}
  1: {documentName: "file4.pdf", documentUrl: "someUrl4"}

So you can use it like so:

<div *ngFor="let docs of data">
  <div *ngFor="let doc of docs">
    <p>file name: {{doc.documentName}}</p>
    <p>file url: {{doc.documentUrl}}</p>
  </div>
</div>

Let me know if you will need any comments thought the code or will have any questions.

P.S. What you really have to now that nesting like this is not recommended by firebase, you should flaten you data. You can read about this here new docs and here old docs

Upvotes: 1

Related Questions