In any web application, pagination is a common feature being used with a table to handle a huge amount of data. This feature can help reduce the data loaded into the table by splitting it into multiples pages. Each page contains a set of data based on the number $per_page given.
Building a pagination feature from scratch can be very painful. Lucky for us, Laravel has made it easy for developers to develop this feature. As simple as adding paginate($per_page) method on a query builder, we can get data together with pagination metadata. Refer to official Laravel documentation for more details: https://laravel.com/docs/8.x/pagination
Laravel API pagination response:
// URL: http://pagination-demo.test/user?page=1
{
"total": 567,
"per_page": 15,
"current_page": 1,
"last_page": 80,
"first_page_url": "http://pagination-demo.test/user?page=1",
"last_page_url": "http://pagination-demo.test/user?page=80",
"next_page_url": "http://pagination-demo.test/user?page=2",
"prev_page_url": null,
"path": "http://pagination-demo.test",
"from": 1,
"to": 15,
"data":[
{
// User record...
},
{
// User record...
}
]
}
Now that we have the response with pagination metadata, we can use it in our Vue.js file. A simple implementation can be done by simply make a loop based on the “last_page” variable. But if the number of pages is large, for instance 50 pages, we don’t want to show each number under the table. It will look weird and hard to navigate.

<nav aria-label="Page navigation">
<ul class="pagination">
<li class="page-item" :class="pagination.current_page == 1 ? 'disabled' : ''"><a class="page-link" href="javascript:void(0)" @click="setPage(pagination.current_page - 1)">Previous</a></li>
<template >
<li class="page-item" v-for="(page, index) in pagination.last_page" :key="index" :class="pagination.current_page == page ? 'active' : ''">
<a class="page-link" @click="setPage(page)">@{{ page }}</a>
</li>
<li class="page-item" :class="pagination.current_page == pagination.last_page ? 'disabled' : ''"><a class="page-link" href="javascript:void(0)" @click="setPage(pagination.current_page + 1)">Next</a></li>
</ul>
<small>Showing @{{ pagination.from }} to @{{ pagination.to }} of @{{ pagination.total }} entries</small>
</nav>
Here how we can improve that. Instead of displaying each page number, we will just display the first page, the last 5 pages from the current_page, the next 5 pages from the current_page, and the last page. The tricky part is how to get the last 5 pages from the current_page and the next 5 pages from the current_page? The answer is to calculate the absolute value of page number against the current_page.
We will put these conditions (refer line no 5) to display the page number.
- page == 1 [Show first page]
- page == pagination.last_page [Show last page]
- Math.abs(page – pagination.current_page) < 5 [Show last 5 pages & next 5 pages from current_page]

<nav aria-label="Page navigation">
<ul class="pagination">
<li class="page-item" :class="pagination.current_page == 1 ? 'disabled' : ''"><a class="page-link" href="javascript:void(0)" @click="setPage(pagination.current_page - 1)">Previous</a></li>
<template v-for="(page, index) in pagination.last_page">
<template v-if="page == 1 || page == pagination.last_page || Math.abs(page - pagination.current_page) < 5">
<li class="page-item" :key="index" :class="pagination.current_page == page ? 'active' : ''">
<a class="page-link" @click="setPage(page)">@{{ page }}</a>
</li>
</template>
</template>
<li class="page-item" :class="pagination.current_page == pagination.last_page ? 'disabled' : ''"><a class="page-link" href="javascript:void(0)" @click="setPage(pagination.current_page + 1)">Next</a></li>
</ul>
<small>Showing @{{ pagination.from }} to @{{ pagination.to }} of @{{ pagination.total }} entries</small>
</nav>
Hopefully, this will help.