问题
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.
回答1:
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
});
}));
回答2:
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 };
});
});
回答3:
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
回答4:
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.
回答5:
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
回答6:
With Angular 6
Breakdown:
I created a Map to store the key/values for future queries.
Fetched the values and added them to the previously created Map
- 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;
}
...
来源:https://stackoverflow.com/questions/46587495/angularfire2-realtime-database-how-to-get-key-and-value