Reputation:
I'm trying to retrieve the whole collection from Firestore and following instructions step by step but all the time there are some errors either map() or, Observable or then() doesn't exist or work.
That's how I've been trying to get it:
import { Injectable } from '@angular/core';
import { Employee } from './employee';
import { AngularFirestore } from '@angular/fire/firestore';
@Injectable({
providedIn: 'root'
})
export class EmployeeService {
FormData: Employee;
constructor(private firestore: AngularFirestore) { }
getEmployees(){
this.firestore.collection('employees').get().then((snapshot) => {
snapshot.docs.forEach(doc => {
console.log(doc);
})
})
}
}
That's what I get for now:
ERROR in src/app/employees/shared/employee.service.ts(16,50): error TS2339: Property 'then' does not exist on type 'Observable'.
Upvotes: 1
Views: 2374
Reputation: 38757
Try the following instead using valueChanges()
. valueChanges()
returns an Observable of data as a synchronized array of JSON objects.
getEmployees(){
this.firestore.collection('employees')
.valueChanges()
.subscribe(docs => {
// loop through each item in the array and log value
docs.forEach(doc => console.log(doc));
});
}
This comes from the documentation for valueChanges(). In case you need to doc id, you can instead use snapshotChanges() in combination with RxJS pipeable operators such as map()
(to create an array of objects with both the id and data):
getEmployees(){
this.firestore.collection('employees')
.snapshotChanges()
.pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data };
});
)
.subscribe(docs => {
// loop through each item in the array and log value
docs.forEach(doc => console.log(doc.id));
});
}
Ideally you should create a class
or interface
to represent the data structure of each "employee" and use that to strongly type the response:
Service:
interface Employee {
someProperty: number;
anotherProperty: string;
yetAnotherProperty: boolean;
}
// ...
// perhaps return the observable so a component using this service can consume the data (can't return from inside subscribe())
getEmployees(): Observable<Employee[]> {
return this.firestore.collection<Employee>('employees').valueChanges();
/* or instead snapshotChanges() with map()
return this.firestore.collection<Employee>('employees')
.snapshotChanges()
.pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data };
});
)
*/
}
Component:
@Component({ /* ... */})
export class SomeComponent {
constructor(private employeeService: EmployeeService) {}
ngOnInit() {
this.employeeService.getEmployees().subscribe(employees => console.log(employees));
}
}
Hopefully that helps!
Upvotes: 2