Back to Course |
How to Build Laravel 11 API From Scratch

Data Pagination via API

Let's talk about pagination for products. Now, on the home page, we have all the products loaded, which, in this case, is twenty products. But in the real world, shops could have hundreds and thousands of products. So we need to paginate them.


In a regular Laravel project, instead of using get(), you would use paginate().

app/Http/Controllers/Api/ProductController.php:

class ProductController extends Controller
{
public function index()
{
$products = Product::with('category')->get();
$products = Product::with('category')->paginate(9);
 
return ProductResource::collection($products);
}
}

And in the Blade, you would do $products->links(), and it would generate the pagination with links.

But in the API, we work only with the data. How do we tell the frontend the links for the pagination, how many records are there, how many pages, and what the next and previous pages are? When using Resources and returning a collection, Laravel handles everything.

After going to /api/products in the client, we returned all records in the data key. Now, at the bottom, we have links and meta keys with the information about pagination.

If we visit the second page in the client, we can see that records start from ID 10 because, in the Controller, we specified to be paginated by nine records.

Now, how do we consume this pagination data in the frontend? There are various ways to do it. You can create your own Vue.js component. For this example, I will use a package called Laravel Vue Pagination.

After installing the Vue.js package via npm, we must import it. Then, we modify the getProducts methods to use pagination in the links and set the default page to one. When calling a component, we specify a data variable. In this case, it is products, and the method which gets called after clicking pagination, in this case, it is getProducts.

resources/js/components/Home.vue:

<template>
// ...
<div class="grid grid-cols-4 gap-4">
<div class="space-y-2" v-for="product in products.data" :key="product.id">
<a href="#">
<img src="http://placehold.it/300x400" :alt="product.name" />
</a>
<a class="text-slate-500 text-xl font-semibold hover:underline">
{{ product.name }}
</a>
<p>${{ product.price }}</p>
<p class="prose-slate">{{ product.description }}</p>
</div>
</div>
 
<TailwindPagination :data="products" @pagination-change-page="getProducts" class="mt-4" />
// ...
</template>
 
<script setup>
import { onMounted, ref } from 'vue';
import { TailwindPagination } from 'laravel-vue-pagination';
 
// ...
 
const getProducts = async (page = 1) => {
await axios.get(`/api/products?page=${page}`)
.then(response => {
products.value = response.data
})
.catch((error) => console.log(error))
}
 
// ...
</script>

In the frontend, we can see the pagination links.

We can see what requests are made in the browser's network tab.