Good afternoon folks,
I have an unordered list that I would like to apply pagination with flexboxes. Any help is highly appreciated:
> <template>
<div id="app">
<ul>
<li v-for="item in items.results" :key="item.id">
{{ item.pub_date }} {{item.image.file}} {{item.title}}
<div >
<span
v-for="downloadable in item.downloadable.filter(d => !!d.document_en)"
:key="downloadable.id"
>{{ downloadable.document_en.file }}</span>
</div>
</li>
</ul>
</div>
</template>
<style>
</style>
CodePudding user response:
That's pretty much state forward.
Create few constants:
const ROW_PER_PAGE = 10;
const CURRENT_PAGE = 0;
add them in your data method:
return {
rowPerPage: ROW_PER_PAGE,
currentPage: CURRENT_PAGE,
items: allMyData
}
use computed property to return only the required number of rows:
computed: {
getPaginatedData() {
const start = this.currentPage * this.rowPerPage;
const end = start this.rowPerPage;
return this.items.slice(start, end); // end index won't be included
}
}
Now simply use this getPaginatedData in your template
<li v-for="item in getPaginatedData" :key="item.id">
The last piece is have buttons to change the page. And on each page change, simply update the currentPage var.
For adding pagination buttons, ofcourse you can create your own component, but if you are less on time then you may use per-developed component. The one which I like is https://getbootstrap.com/docs/4.0/components/pagination/
CodePudding user response:
Step 1: Create Pagination.vue component
<template>
<ul >
<li >
<button type="button" @click="onClickFirstPage" :disabled="isInFirstPage">First</button>
</li>
<li >
<button type="button" @click="onClickPreviousPage" :disabled="isInFirstPage">Previous</button>
</li>
<li :key="page.id" v-for="page in pages" >
<button type="button" @click="onClickPage(page.name)" :disabled="page.isDisabled"
:>{{ page.name }}</button>
</li>
<li >
<button type="button" @click="onClickNextPage" :disabled="isInLastPage">Next</button>
</li>
<li >
<button type="button" @click="onClickLastPage" :disabled="isInLastPage">Last</button>
</li>
</ul>
</template>
<script>
export default {
name: 'pagination',
props: {
maxVisibleButtons: {
type: Number,
required: false,
default: 3
},
totalPages: {
type: Number,
required: true
},
perPage: {
type: Number,
required: true
},
currentPage: {
type: Number,
required: true
}
},
computed: {
isInFirstPage () {
return this.currentPage === 1
},
isInLastPage () {
if (this.totalPages === 0) {
return true
}
return this.currentPage === this.totalPages
},
startPage () {
// When on the first page
if (this.currentPage === 1) {
return 1
}
// When on the last page
if (this.totalPages < this.maxVisibleButtons) {
return 1
}
if (this.currentPage === this.totalPages) {
return this.totalPages - this.maxVisibleButtons 1
}
// When in between
return this.currentPage - 1
},
endPage () {
if (this.totalPages === 0) {
return 1
}
if (this.totalPages < this.maxVisibleButtons) {
return this.totalPages
}
return Math.min(this.startPage this.maxVisibleButtons - 1, this.totalPages)
},
pages () {
const range = []
for (let i = this.startPage; i <= this.endPage; i = 1 ) {
range.push({
name: i,
isDisabled: i === this.currentPage
})
}
return range
}
},
methods: {
onClickFirstPage () {
this.$emit('pagechanged', 1)
},
onClickPreviousPage () {
this.$emit('pagechanged', this.currentPage - 1)
},
onClickPage (page) {
this.$emit('pagechanged', page)
},
onClickNextPage () {
this.$emit('pagechanged', this.currentPage 1)
},
onClickLastPage () {
this.$emit('pagechanged', this.totalPages)
},
isPageActive (page) {
return this.currentPage === page
}
}
}
</script>
<style scoped>
.pagination {
list-style-type: none;
float: right;
margin: 10px 0;
}
.pagination-item {
display: inline-block;
}
.active {
background-color: #943849;
color: #ffffff !important;
font-weight: bold;
}
button[disabled], html input[disabled] {
cursor: default;
color: lightgray;
}
</style>
Step 2: Add Pagination component reference in app.vue component
import Pagination from './components/Pagination'
Add Pagination component in app.vue
export default {
components: {
Pagination,
},
Step 3: Create model data with pagination object
data() {
return {
items:[],
page: 1,
totalPages: 0,
totalRecords: 0,
recordsPerPage: 10
}
},
Step 4: Create an methods for load data and adding pagination
methods: {
loadPressRelease () {
this.showLoader = true
axios.get(`https://zbeta2.mykuwaitnet.net/backend/en/api/v2/media-center/press-release/?page=${this.page}&page_size=${this.recordsPerPage}&type=5`)
.then(response => {
this.showLoader = false
this.items = response.data
this.totalPages = Math.ceil(response.data.count / this.recordsPerPage)
this.totalRecords = response.data.count
})
},
onPageChange(page) {
this.page = page
this.loadPressRelease()
}
}
Step 5: Default page load on created methods
created() {
this.loadPressRelease()
},
Step 6: HTML template with pagination reference
<div id="app">
<ul>
<li v-for="item in items.results" :key="item.id">
{{ item.pub_date }} {{item.image && item.image.file}} {{item.title}}
<div >
<span v-for="downloadable in item.downloadable.filter(d => !!d.document_en)"
:key="downloadable.id">{{ downloadable.document_en.file }}
</span>
</div>
</li>
</ul>
<Pagination v-if="items.results" :total-pages="totalPages" :per-page="this.recordsPerPage" :current-page="page" @pagechanged="onPageChange" />
</div>
