In this tutorial, I will show you how to make Pagination in a Vue.js Application with existing API (Server Side pagination) using Axios and Bootstrap-Vue.
Related Posts:
– Vue.js 2 CRUD Application with Vue Router & Axios
– Vue.js JWT Authentication with Vuex and Vue Router
– Vue File Upload example using Axios
Using Vuetify Pagination Component:
Vuetify Pagination (Server side) example
Contents
- Vue Pagination with API overview
- Bootstrap-Vue Pagination component
- Technology
- Setup Vue.js Application
- Setup Bootstrap Vue for Vue Pagination App
- Initialize Axios
- Create Data Service
- Create Vue Component with Pagination
- Configure Port for Vue Pagination App
- Run Vue Pagination App
- Conclusion
- Further Reading
- Source Code
Vue Pagination with API overview
One of the most important things to make a website friendly is the response time, and pagination comes for this reason. For example, this bezkoder.com website has hundreds of tutorials, and we donโt want to see all of them at once. Paging means displaying a small number of all, by a page.
Assume that we have tutorials table in database like this:
Our Vue.js app will display the result with pagination:
Change to a page with larger index:
We can change quantity of items per page:
Or paging with filter:
The API for this Vue client can be found at one of following posts:
– Node.js Express Pagination with MySQL
– Node.js Express Pagination with PostgreSQL
– Node.js Express Pagination with MongoDB
– Spring Boot Pagination & Filter example | Spring JPA, Pageable
– Spring Boot MongoDB Pagination example with Spring Data
These Servers will exports API for pagination (with/without filter), here are some url samples:
/api/tutorials?page=1&size=5
/api/tutorials?size=5
: using default value for page/api/tutorials?page=1
: using default value for size/api/tutorials?title=data&page=1&size=3
: pagination & filter by title containing ‘data’
This is structure of the response (server-side pagination) for the HTTP GET request:
{
"totalItems": 8,
"tutorials": [...],
"totalPages": 3,
"currentPage": 1
}
This is a kind of server-side paging, where the server sends just a single page at a time. Bootstrap-Vue
Pagination component supports this scenario, so we actually only need to use tutorials
and totalItems
when working with this library.
Bootstrap-Vue Pagination component
Bootstrap-Vue provides Pagination component (b-pagination
) that enables the user to select a specific page from a range of pages.
This is a basic Pagination component:
<b-pagination
v-model="currentPage"
:total-rows="rows"
:per-page="perPage"
></b-pagination>
v-model
: bind the current page number valuetotal-rows
: total itemsper-page
: number of items per page
Notice that page numbers are indexed from 1, the number of pages is computed from total-rows
and per-page
.
You can also customize the appearance of Pagination component with content/size of the buttons, pill style like following samples:
The corresponding code will be:
<b-pagination
v-model="page"
:total-rows="count"
:per-page="pageSize"
size="sm"
></b-pagination>
<b-pagination
v-model="page"
:total-rows="count"
:per-page="pageSize"
size="lg"
></b-pagination>
<b-pagination
v-model="page"
:total-rows="count"
:per-page="pageSize"
pills
></b-pagination>
<b-pagination
v-model="page"
:total-rows="count"
:per-page="pageSize"
></b-pagination>
<b-pagination
v-model="page"
:total-rows="count"
:per-page="pageSize"
first-number
last-number
></b-pagination>
<b-pagination
v-model="page"
:total-rows="count"
:per-page="pageSize"
first-text="First"
prev-text="Prev"
next-text="Next"
last-text="Last"
></b-pagination>
For more details, please visit:
BootstrapVue Pagination Component Reference
For handling page changes, we use change
event:
<template>
<div>
<b-pagination
@change="handlePageChange"
></b-pagination>
...
</div>
</div>
</template>
<script>
export default {
data() {
return {
page: 1,
};
},
methods: {
handlePageChange(value) {
this.page = value;
},
},
};
</script>
handlePageChange
will be invoked whenever the page changes via user interaction (click), value
is the selected page number.
Technology
- Vue 2.6
- axios 0.19.2
- bootstrap 4.5.0
- bootstrap-vue 2.16.0
Setup Vue.js Application
Open cmd at the folder you want to save Project folder, run command:
vue create vue-js-client-crud
You will see some options, choose default (babel, eslint).
After the process is done. We create new folders and files like the following tree:
public
index.html
src
components
AddTutorial.vue
Tutorial.vue
TutorialsList.vue
services
TutorialDataService.js
App.vue
main.js
package.json
You can follow step by step, or get source code in this post:
Vue.js 2 CRUD Application with Vue Router & Axios
The Vue Project contains structure that we only need to add some changes (in TutorialsList.vue and TutorialDataService.js) to make the pagination work well.
Or you can get the new Github source code at the end of this tutorial.
Setup Bootstrap Vue for Vue Pagination App
We need to install both Bootstrap core and Bootstrap Vue with command:
npm install bootstrap-vue bootstrap
Register BootstrapVue
in your app entry point:
src/main.js
import Vue from 'vue'
import App from './App.vue'
import { BootstrapVue } from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
...
Vue.use(BootstrapVue)
new Vue({
render: h => h(App),
}).$mount('#app')
Initialize Axios
Now we’re gonna install axios with command: npm install axios
.
Then, under src folder, we create http-common.js file like this:
import axios from "axios";
export default axios.create({
baseURL: "http://localhost:8080/api",
headers: {
"Content-type": "application/json"
}
});
Remember to change the baseURL
, it depends on REST APIs url that your Server configures.
For more details about ways to use Axios, please visit:
Axios request: Get/Post/Put/Delete example
Create Data Service
In this step, we’re gonna create a service that uses axios
object above to send HTTP requests.
services/TutorialDataService.js
import http from "../http-common";
class TutorialDataService {
getAll(params) {
return http.get("/tutorials", { params });
}
// other CRUD methods
}
export default new TutorialDataService();
In the code above, you can see that we pass params
object to GET method.
The params
object will have one, two or all fields: title
, page
, size
.
Create Vue Component with Pagination
This component has:
- a search bar for finding Tutorials by title.
- a select element for quantity of items per page.
- a Bootstrap-Vue Pagination component
- a tutorials array displayed as a list on the left.
- a selected Tutorial which is shown on the right.
components/TutorialsList.vue
<template>
<div class="list row">
<div class="col-md-8">
<div class="input-group mb-3">
<input
type="text"
class="form-control"
placeholder="Search by title"
v-model="searchTitle"
/>
<div class="input-group-append">
<button
class="btn btn-outline-secondary"
type="button"
@click="page = 1; retrieveTutorials();"
>
Search
</button>
</div>
</div>
</div>
<div class="col-md-12">
<div class="mb-3">
Items per Page:
<select v-model="pageSize" @change="handlePageSizeChange($event)">
<option v-for="size in pageSizes" :key="size" :value="size">
{{ size }}
</option>
</select>
</div>
<b-pagination
v-model="page"
:total-rows="count"
:per-page="pageSize"
prev-text="Prev"
next-text="Next"
@change="handlePageChange"
></b-pagination>
</div>
<div class="col-md-6">
<h4>Tutorials List</h4>
<ul class="list-group" id="tutorials-list">
<li
class="list-group-item"
:class="{ active: index == currentIndex }"
v-for="(tutorial, index) in tutorials"
:key="index"
@click="setActiveTutorial(tutorial, index)"
>
{{ tutorial.title }}
</li>
</ul>
</div>
...
</div>
</template>
<script>
export default {
...
}
</script>
We will have following properties in data
:
– search and display Tutorials:
searchTitle
tutorials
currentTutorial
andcurrentIndex
– pagination:
page
: current pagecount
: total pagespageSize
: number of items in each page
For retrieving pagination data, we’re gonna use TutorialDataService.getAll()
methods.
<template>
...
</template>
<script>
import TutorialDataService from "../services/TutorialDataService";
export default {
name: "tutorials-list",
data() {
return {
tutorials: [],
currentTutorial: null,
currentIndex: -1,
searchTitle: "",
page: 1,
count: 0,
pageSize: 3,
pageSizes: [3, 6, 9],
};
},
methods: {
getRequestParams(searchTitle, page, pageSize) {
let params = {};
if (searchTitle) {
params["title"] = searchTitle;
}
if (page) {
params["page"] = page - 1;
}
if (pageSize) {
params["size"] = pageSize;
}
return params;
},
retrieveTutorials() {
const params = this.getRequestParams(
this.searchTitle,
this.page,
this.pageSize
);
TutorialDataService.getAll(params)
.then((response) => {
const { tutorials, totalItems } = response.data;
this.tutorials = tutorials;
this.count = totalItems;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
handlePageChange(value) {
this.page = value;
this.retrieveTutorials();
},
handlePageSizeChange(event) {
this.pageSize = event.target.value;
this.page = 1;
this.retrieveTutorials();
},
...
}
};
</script>
Let me explain some lines of code.
In the retrieveTutorials()
method:
– We get searchTitle
, page
, pageSize
value and transform them into params
object:
{
"title": searchTitle,
"page": page - 1,
"size": pageSize
}
– We use tutorials
and totalItems
as count
value from the response data:
{
"totalItems": 8,
"tutorials": [...],
"totalPages": 3,
"currentPage": 1
}
handlePageChange()
and handlePageSizeChange()
methods are for setting new page
and pageSize
and then invokes retrieveTutorials()
that updates the tutorials List after pagination information changes.
Configure Port for Vue Pagination App
Because most of HTTP Server use CORS configuration that accepts resource sharing retricted to some sites or ports, so we also need to configure port for our App.
In project root folder, create vue.config.js file with following content:
module.exports = {
devServer: {
port: 8081
}
}
Run Vue Pagination App
First you need to run the Server at one of following posts:
- Node.js Express Pagination with MySQL
- Node.js Express Pagination with PostgreSQL
- Node.js Express Pagination with MongoDB
- Spring Boot Pagination & Filter example | Spring JPA, Pageable
- Spring Boot MongoDB Pagination example with Spring Data
Then you can run our App with command: npm run serve
.
If the process is successful, open Browser with Url: http://localhost:8081/
and check it.
Conclusion
Today we’ve built a Vue Pagination example that use Axios to consume API (server-side pagination) successfully with Bootstrap Vue for Pagination UI. I hope you apply it in your project at ease.
If you want to use Vuetify Pagination Component, please visit:
Vuetify Pagination (Server side) example
Happy learning, see you again!
Further Reading
- Bootstrap Vue Pagination Component
- Bootstrap Vue – Getting Started
- https://www.npmjs.com/package/axios
For more details about ways to use Axios, please visit:
Axios request: Get/Post/Put/Delete example
Source Code
You can find the complete source code for this tutorial on Github.
Nice tutorial! Funny enough, what I really liked was the screenshot of various ways you might style pagination e.g. circular buttons and what not. I also like how you tied it into how you’d actually use against a server API with subsequent requests as you page ๐
I’m building a ui component library for react, vue 3, angular, and svelte and so I looked at many many tutorials, github source code, etc., etc., before starting to code mine and there are a couple of things I think are very important for a pagination component folks should consider:
– configurability of the view
– supporting sibling offset of both 1 or 2 (ant design and zendesk appear to use padding or offset of 1 but I’ve seen many others that use offset of 2; so I decided to just support both).
– accessibility (aria-current, aria-disabled, etc., are crucial to support screenreaders and build an inclusive component)
– ideally, support Vue 3’s composition api. Once I dug in a bit I found the vue 3 composition api way of doing things much more flexible and clean
I’d invite you to look at AgnosticUI’s vue 3 pagination implementation and see what you think bezkoder — thanks for this tutorial and the visualizations too ๐
If you have time could you to make a pagination from scratch server side also ?
This would be axios + pinia or any state management
Hi, you can find tutorials for server side pagination that I mentioned in this tutorial.
Thank you for the tutorial!
I really respect your tutorials. The article has really peaks my interest!
Thank you for an additional wonderful tutorial!
Thanks!
Thank you for this tutorial! It really helped me finish up my pagination links!
What part of this is server paginated? You get all the tutorials from the server. This is not true server-side pagination in which you retrieve only what you need for that page
Hi, this is exactly Vue Client for Server-side Pagination where the server takes a number of parameters from the client (current page, page size…) and performs whatever search required to get just the relevant records.
This Vue Client only needs to send request with page, size and searching field.
Do you want the Client work as a server? I don’t think that it is a good idea.
Thank you! This Vue tutorial is exactly what I want to know about frontend Pagination.