Firestore + AngularFire2 pagination ( query items by range - .startAfter(lastVisible) )
I had the same Problem and this is what i did.
Service
private _data: BehaviorSubject<Scores[]>;
public data: Observable<Scores[]>;
latestEntry: any;
constructor(private afs: AngularFirestore) {}
// You need to return the doc to get the current cursor.
getCollection(ref, queryFn?): Observable<any[]> {
return this.afs.collection(ref, queryFn).snapshotChanges().map(actions => {
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
const doc = a.payload.doc;
return { id, ...data, doc };
});
});
}
// In your first query you subscribe to the collection and save the latest entry
first() {
this._data = new BehaviorSubject([]);
this.data = this._data.asObservable();
const scoresRef = this.getCollection('scores', ref => ref
.orderBy('score', 'desc')
.limit(6))
.subscribe(data => {
this.latestEntry = data[data.length - 1].doc;
this._data.next(data);
});
}
next() {
const scoresRef = this.getCollection('scores', ref => ref
.orderBy('scores', 'desc')
// Now you can use the latestEntry to query with startAfter
.startAfter(this.latestEntry)
.limit(6))
.subscribe(data => {
if (data.length) {
// And save it again for more queries
this.latestEntry = data[data.length - 1].doc;
this._data.next(data);
}
});
}
Component
scores$: Observable<Scores[]>;
...
ngOnInit() {
this.yourService.first();
this.scores$ = this.yourService.data;
}
nextPage() {
this.yourService.next();
}
Source Tutorial Link
AngularFire2 used for FireStore database operations
using below methods:
For Next Page
nextPage() {
this.disable_next = true;
this.firestore.collection('People', ref => ref
.limit(5)
.orderBy('timestamp', 'desc')
.startAfter(this.lastInResponse)
).get()
.subscribe(response => {
if (!response.docs.length) {
this.disable_next = true;
return;
}
this.firstInResponse = response.docs[0];
this.lastInResponse = response.docs[response.docs.length - 1];
this.tableData = [];
for (let item of response.docs) {
this.tableData.push(item.data());
}
this.pagination_clicked_count++;
this.push_prev_startAt(this.firstInResponse);
this.disable_next = false;
}, error => {
this.disable_next = false;
});
}
For Previous Page
prevPage() {
this.disable_prev = true;
this.firestore.collection('People', ref => ref
.orderBy('timestamp', 'desc')
.startAt(this.get_prev_startAt())
.endBefore(this.firstInResponse)
.limit(5)
).get()
.subscribe(response => {
this.firstInResponse = response.docs[0];
this.lastInResponse = response.docs[response.docs.length - 1];
this.tableData = [];
for (let item of response.docs) {
this.tableData.push(item.data());
}
//Maintaing page no.
this.pagination_clicked_count--;
//Pop not required value in array
this.pop_prev_startAt(this.firstInResponse);
//Enable buttons again
this.disable_prev = false;
this.disable_next = false;
}, error => {
this.disable_prev = false;
});
}
Check complete tutorial and demo on this link