Reputation: 18392
Using bootstrap-vue pagination component:
<b-pagination
v-model="currentPage"
:total-rows="rows"
:per-page="perPage"
></b-pagination>
Component.vue:
export default class Links extends Vue {
public currentPage: number = 1
public perPage: number = 20
public rows: number = 1
@Watch('currentPage')
onCurrentPageChange(page: number) {
const startAt = page * this.perPage - this.perPage
db.collection('links')
.orderBy('created', 'desc')
.startAt(startAt)
.limit(this.perPage)
.get()
.then(snap => {
console.log(snap.docs)
})
}
}
When currentPage
value changes, i fetch new DB values with startAt
but it returns nothing. My firestore has the following documents with the fields:
How can i make a normal pagination with offsets / limits?
Upvotes: 0
Views: 2083
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.
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: 2