Reputation: 21
I'm trying to paginate my data from firebase realtime database.
Do I have to change to firestore ? Where all is explain in Google's doc (https://firebase.google.com/docs/firestore/query-data/query-cursors) or it's also possible with rtdb ?
Here is my code (i'm using vue js) :
loadConcerts ({commit}) {
commit('setLoading', true)
firebase.database().ref('concerts')
.orderByChild('expires')
.startAt(Date.now() / 1e3)
.limitToFirst(10)
.once('value')
.then(data => {
const concerts = []
data.forEach(element => {
concerts.push({
id: element.key,
title: element.val().title,
day: element.val().day,
ticketlink: element.val().ticketlink,
description: element.val().descriptio
})
})
commit('setLoadedConcerts', concerts)
commit('setLoading', false)
})
.catch(
(error) => {
console.log(error)
commit('setLoading', false)
}
)
},
I would like to add pagination after 10 results, or infinite scrolling.
Upvotes: 2
Views: 1391
Reputation: 1160
I have also had similar problem with pagination. The documentation seems to be insufficient i.e they show you how to go to next page but not how to move back to the previous page. Its just frustrating really.
I am using firestore
Below is how i implemented a simple pagination. I have already configured VueFire
, Firebase
and BootstrapVue
i'll head straight to the code.
What to do different that no one shows you.
VueFire
programmatic binding instead of declarative binding see herefirstVisible
item in firebase
run documentSnapshots.docs[0]
<template>
<div>
<p>{{countries}}</p>
<b-button-group size="lg" class="mx-2">
<b-button :disabled="prev_btn" @click="previous" >«</b-button>
<b-button :disabled="next_btn" @click="next">»</b-button>
</b-button-group>
</div>
</template>
<script>
import firebase from 'firebase/app'
import 'firebase/auth'
import { db } from '../main'
export default {
name: 'Countries',
data () {
return {
countries: [],
limit: 2,
lastVisible: '',
firstVisible: '',
next_btn: false,
prev_btn: true
}
},
methods: {
next () {
if (!this.next_btn) {
// bind data with countries
this.$bind('countries', db.collection('Countries').orderBy('createdAt').startAfter(this.lastVisible).limit(this.limit))
// set last and first visible items
db.collection('Countries').orderBy('createdAt').startAfter(this.lastVisible).limit(this.limit).get().then(documentSnapshots => {
this.lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1]
this.firstVisible = documentSnapshots.docs[0]
}).then(() => {
// Peep on the next next query to see if it gives zero
db.collection('Countries').orderBy('createdAt').startAfter(this.lastVisible).limit(this.limit).get()
.then(snap => {
if (snap.size === 0) {
//disable button if the next peeped result gets zero
this.next_btn = true
// enable previous button
this.prev_btn = false
} else {
// enable next button if peeped result is not zero
this.next_btn = false
// enable previous button
this.prev_btn = false
}
})
})
}
},
previous () {
// Ensure previous is not zero
db.collection('Countries').orderBy('createdAt').endBefore(this.firstVisible).limitToLast(this.limit).get().then(snap => { return snap.size })
.then(size => {
//confirm is not zero here
if (size !== 0) {
//bind the previous to countries
this.$bind('countries', db.collection('Countries').orderBy('createdAt').endBefore(this.firstVisible).limitToLast(this.limit))
// Set last and first visible
db.collection('Countries').orderBy('createdAt').endBefore(this.firstVisible).limitToLast(this.limit).get().then(documentSnapshots => {
this.lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1]
this.firstVisible = documentSnapshots.docs[0]
}).then(() => {
// peep the next previous query
db.collection('Countries').orderBy('createdAt').endBefore(this.firstVisible).limitToLast(this.limit).get()
.then(snap => {
if (snap.size === 0) {
//if next peeped previous button gets 0 disable
this.prev_btn = true
this.next_btn = false
} else {
//if next peeped result is does not get 0 enable buttons
this.prev_btn = false
this.next_btn = false
}
})
})
}
})
}
},
mounted () {
// run first query and bind data
this.$bind('countries', db.collection('Countries').orderBy('createdAt').limit(this.limit))
// set last and first Visible
db.collection('Countries').orderBy('createdAt').limit(this.limit).get().then(documentSnapshots => {
this.lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1]
this.firstVisible = documentSnapshots.docs[0]
}).then(() => {
// peep to check if next should be on or off
db.collection('Countries').orderBy('createdAt').startAfter(this.lastVisible).limit(this.limit).get()
.then(snap => {
if (snap.size === 0) {
this.next_btn = true
}
})
})
}
}
</script>
Upvotes: 1