AngularFire2: Realtime Database: how to get key and value

Viewed 20694

I use AngularFire2 to get data from Firebase Database (realtime).

What I have done:

  • Firebase Database

{ “class” : { “student” : { “Tom” : “male”, “Mary” : “female”, “Peter” : “male”, “Laura” : “female” }, "numberOfStudent” : 10 } }

  • app.component.ts

    import { AngularFireDatabase } from 'angularfire2/database';
    import { Observable } from 'rxjs/Observable';
    
    ...
    export class AppComponent {
    
       class: Observable<any>;
       students: Observable<any[]>;
    
    constructor(private db: AngularFireDatabase) {
       this.class = db.object(‘class’).valueChanges();
       this.students = db.list(‘class/student’).snapshotChanges();
     }
    
    } 
    
  • app.component.html:

<h2>Class size: {{ (class | async)?.numberOfStudent }}</h2>
<ul>
  <li *ngFor="let i of students | async">
    {{i.key}} : {{i.value}}
  </li>
</ul>

What happened:

Class size: 10

Tom :

Mary :

Peter :

Laura :

It doesn't return the value of list.

Any suggestion is appreciated.

7 Answers

UPD

with new Angular 6 and RxJS 6 you'll do this:

import { map } from 'rxjs/operators';
// ...
return this.fb.list(`/path/to/list`)
  .snapshotChanges()
  .pipe(map(items => { .            // <== new way of chaining
    return items.map(a => {
      const data = a.payload.val();
      const key = a.payload.key;
      return {key, data};           // or {key, ...data} in case data is Obj
    });
  }));

AngularFire2 library has gone through some breaking changes since @rickdroio's answer. The following is an updated version of the solution:

afs.collection<Shirt>('class/student').snapshotChanges().map(actions => {
  return actions.map(a => {
    const data = a.payload.val();
    const id = a.payload.id;
    return { id, ...data };
  });
});

I managed to get the key and value of list. Just follow some tips below:

  • Make sure using snapshotChanges()

<li *ngFor="let i of seats | async">
    {{i.key}} : {{i.payload.val()}}
</li>

It worked for me, but I am still opening to receive more best practices

According to guideline available on https://github.com/angular/angularfire2/blob/master/docs/firestore/collections.md you could do something like that:

afs.collection<Shirt>('class/student').snapshotChanges().map(actions => {
      return actions.map(a => {
        const data = a.payload.doc.data();
        const id = a.payload.doc.id;
        return { id, ...data };
      });
    });

It will return a similar array like previous Firebase db.

your problem is your JSON object students is not an array, and you are trying to loop through it.

    "student" : { “Tom” : “male”, “Mary” : “female”, “Peter” : “male”, “Laura” :
“female” }, "numberOfStudent” : 10 }

you need to make your students a list of objects in order to loop through them, like so:

   "student" :
[ { "name" : "Tom", "sex" : male}, {"name" : "Mary, "sex" : "female" }, ... ]

the loop through let i of student | async and access the name and sex i?.name, i?.sex

With Angular 6
Breakdown:

  1. I created a Map to store the key/values for future queries.

  2. Fetched the values and added them to the previously created Map

  3. Created two helper methods to get the key or the value separately.

todosKeyValues: Map<string, Todo> = new Map();

constructor(private databaseFB: AngularFireDatabase) {
    this.fetchKeyValues();
 }

private fetchKeyValues() {
    this.databaseFB.list('/').snapshotChanges().subscribe(actions => {
      actions.forEach(action => {
        const value = action.payload.val();
        const id = action.payload.key;
        this.todosKeyValues.set(id, value);
      });
    });
  }


 private getKey(id: number): string {
 const foundEntry = Array.from(this.todosKeyValues.entries())
    .filter(entry =>entry[1].id === id).pop();
   return foundEntry ? foundEntry[0] : undefined;
  }

  private getTodo(id: number): Todo {
    const foundEntry = Array.from(this.todosKeyValues.entries())
    .filter(entry => entry[1].id === id).pop();
      //index 0 is the key, index 1 is the value
    return foundEntry ? foundEntry[1] : undefined;
  }
  ...

I tried all of these above, none of this worked as of Angular 6 this worked for me

   const m = this.firestore.collection("class/student").snapshotChanges();
    m.subscribe(res =>{
      console.log(res)
      res.forEach(res => {
        const value = res.payload.doc.data();
        const id = res.payload.doc.id;
        console.log(value," ",id)
      });
    })

A lot of methods of angular fire went obsolete. The key lied in vs code suggestion, in future if this doesn't work you would have to explore the provided similarly. For now

res.payload.doc.data()
res.payload.id

Would work.

Related