In this example, we will see the complete Vue Pagination Tutorial with Laravel backend from scratch. We will install some fake data using faker library and then use client-side http network request promise based library Axios to send a request to Laravel server, fetch and display the data in the form of Pagination. We will build pagination in Vue from scratch.

Final Output

Vue Pagination Tutorial

We are using Laravel 5.6 for this example. So first, we need to install Laravel. I am using Laravel Valet for this tutorial. If you are not using Valet then just you need to create a Laravel project using the following command.

Step 1: Install Laravel.

If you do not want to use Laravel Valet, then you can install Laravel using the following command.

composer create-project laravel/laravel paginate --prefer-dist

Go to your project folder and start the development server by the following command.

php artisan serve

Laravel Valet

If you are using Laravel Valet, then you need to go to your project folder and hit the following command.

laravel new paginate

You can access the project using the following URL: http://paginate.test/

If you are new to Laravel Valet, then check out the official documentation. It is effortless to get up and run.

Step 2: Install NPM dependencies and setup db.

Go to your project folder.

cd paginate

Install the NPM dependencies using the following command.

npm install

Now, Vue.js is pre-configured in Laravel. So, you need to compile the CSS and JS file using the following command.

npm run dev

Now, configure the database inside the .env file.

DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=paginate DB_USERNAME=root DB_PASSWORD=root

Laravel come up with two migration files by default. So let us use that and create the table in the database using the following command.

php artisan migrate

It will create users and password_resets table.

Step 3: Generate Fake users data.

Now, to paginate the data, we need some amount of data. For this example, I am using faker library to generate the fake users’ data. We use the model factory to create and persist the data in the database. You can see the factory file inside database >> factories >> UserFactory.php file.

<?php // UserFactory.php use Faker\Generator as Faker; /* |-------------------------------------------------------------------------- | Model Factories |-------------------------------------------------------------------------- | | This directory should contain each of the model factory definitions for | your application. Factories provide a convenient way to generate new | model instances for testing / seeding your application's database. | */ $factory->define(App\User::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret 'remember_token' => str_random(10), ]; });

We generate 100 rows of data. So go to your terminal and enter the following command.

php artisan tinker

You can use it to interact with our Laravel application. Now, generate the data.

factory(App\User::class, 100)->create();

It generates random data up to 100 rows.

Step 4: Create routes and controllers.

Now, we need to first create an authentication scaffold. So type the following command.

php artisan make:auth

If you do not use auth scaffold, then you can create your view, it does not matter here.

This scaffold also gives us some fundamental bootstrap views to work with.

In our tutorial, we will be going to make two UserControllers.

UserController(It handles the Laravel view) UserController(Inside API folder, responsible for the API response)

Now, create the first UserController using the following command.

php artisan make:controller UserController

In this controller file, write the following code.

// UserController.php <?php namespace App\Http\Controllers; use App\User; use Illuminate\Http\Request; use App\Http\Resources\UserResource; class UserController extends Controller { public function index() { return view('users.index'); } }

We have not created the index view, so inside resources >> views folder, create a directory called users and inside that, create one file called index.blade.php file.

@extends('layouts.app') @section('content') <div class="container"> Users View </div> @endsection

Now, we need to define the route for this inside routes >> web.php file.

<?php // web.php Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', 'HomeController@index')->name('home'); Route::get('/users', 'UserController@index')->name('users.index');

Create the second UserController.php file inside app >> Http >> Controllers >> API folder.

php artisan make:controller API\\UserController

Write the following code inside this UserController.php file.

<?php // API/UserController.php namespace App\Http\Controllers\API; use App\User; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class UserController extends Controller { public function index() { return User::paginate(10); } }

Now, define routes in the routes >> api.php file.

<?php // api.php use Illuminate\Http\Request; Route::get('/users', 'API\UserController@index');

Now, I can test in this route: http://paginate.test/api/users

Your URL may be different like this: http://localhost:8000/api/users

In above image, I have minimized the items so that, you can see our object’s whole structure.

So, we have created an API, now Vue needs to consume it. Laravel’s paginate function gives us the metadata, which we can use to design our Vue Paginate Component.

Step 5: Display the users at frontend.

Inside resources >> assets >> js >> components folder, by default there is one Vue component called ExampleComponent.vue file. You need to remove this and inside components folder, create one more folder called users.

Inside users folder, create one file called Index.vue.

// Index.vue <template> <div class="row justify-content-center"> <div class="col-md-10"> <div class="card"> <div class="card-header">Users</div> <div class="card-body"> User Data </div> </div> </div> </div> </template> <script> export default { } </script>

Okay, now we need to update the app.js file inside resources >> assets >> js folder.

// app.js require('./bootstrap'); window.Vue = require('vue'); Vue.component('users-list', require('./components/users/Index.vue')); const app = new Vue({ el: '#app' });

So, we have created our users-list component.

Now, we need to display this component at this URL: http://paginate.test/users

So, what we need to do is that inside index.blade.php file under resources >> views >> users folder, we need to add this users-list component.

@extends('layouts.app') @section('content') <div class="container"> <users-list></users-list> </div> @endsection

Okay, now the only remaining thing is to fetch and display the data.

So write the following code inside Index.vue file.

// Index.vue <template> <div class="row justify-content-center"> <div class="col-md-10"> <div class="card"> <div class="card-header">Users</div> <div class="card-body"> <user v-for="user in users" :user="user" :key="user.id"> </user> </div> </div> </div> </div> </template> <script> import User from './partials/User'; export default { components: { User }, data() { return { users: [] } }, mounted() { this.fetchUsers(); }, methods: { fetchUsers() { axios.get('/api/users/').then((res) => { this.users = res.data.data; }); } } } </script>

Create a folder inside users folder called partials and inside that folder, create one Vue component called User.vue.

// User.vue <template> <div class="media"> <div class="media-body"> <h4 class="media-heading"> {{ user.name }} </h4> </div> </div> </template> <script> export default { props: ['user'] } </script>

When the component is mounted, we use the client side HTTP library to send a network request to the Laravel server and get the data and assign it to the user’s array.

We are getting paginated data, so at this time, we are just getting first ten rows of the data.

So, how we can fetch the other data in the structure of pagination. Laravel provides a URL structure in which you can pass the Query string of page, and you can get the other data. The structure is like the following.

http://paginate.test/api/users?page=2

Here, you can change the page value, and we can fetch according to that data. So we need to perform same logic in the Vue.

Step 6: Create a Pagination Vue component.

Inside resources >> assets >> js >> components >> users folder, create new folder called pagination. Inside that folder, create one file called Pagination.vue file.

Now, I am writing the whole logic behind the Vue Pagination inside that component.

// Pagination.vue <template> <nav> <ul class="pagination pagination-lg"> <li class="page-item" :class="{ 'disabled': meta_data.prev_page_url === null }"> <a href="#" class="page-link" @click="next(meta_data.current_page-1)"> « </a> </li> <li class="page-item" v-for="page in meta_data.last_page" :key="page" :class="{ 'active':meta_data.current_page === page }"> <a href="#" @click.prevent="next(page)" class="page-link"> {{ page }} </a> </li> <li class="page-item" :class="{ 'disabled': meta_data.current_page === meta_data.last_page }"> <a href="#" class="page-link" @click="next(meta_data.current_page+1)"> » </a> </li> </ul> </nav> </template> <script> export default { props: ['meta_data'], methods: { next(page) { this.$emit('next', page); } } } </script>

Here, I have done lots of code. So let us get understand first.

Here, In this component, I have used one property called meta_data. This property comes from parent component called Index.vue file, which sends a network request to the server and fetches the data along with meta data like current_page, last_page, and other properties.

The logic here is, if we are at first page, we need to disable the left arrow page button, and if we are at last page, then we need to disable to right arrow page button.

I have written that logic by compared that meta_data provided by Laravel Paginate function.

Also, this component emits an event called next with the parameter page number, so when we click the page number like 1 or 2 or 3, we get the same data from the API.

So the parent component listens to this event and uses that page number provided by the event parameter and call an API and fetch the data according to it.

Our final Index.vue component looks like this.

// Index.vue <template> <div class="row justify-content-center"> <div class="col-md-10"> <div class="card"> <div class="card-header">Users</div> <div class="card-body"> <user v-for="user in users" :user="user" :key="user.id"> </user> <pagination :meta_data="meta_data" v-on:next="fetchUsers"> </pagination> </div> </div> </div> </div> </template> <script> import User from './partials/User'; import Pagination from './pagination/Pagination'; export default { components: { User, Pagination }, data() { return { users: [], meta_data: { last_page: null, current_page: 1, prev_page_url: null } } }, mounted() { this.fetchUsers(); }, methods: { fetchUsers(page = 1) { axios.get('/api/users/', { params: { page } }).then((res) => { this.users = res.data.data; this.meta_data.last_page = res.data.last_page; this.meta_data.current_page = res.data.current_page; this.meta_data.prev_page_url = res.data.prev_page_url; }); } } } </script>

So we are getting that page from the emitter and call the API and Laravel returns a JSON object containing that data. Then, we attach that data to our user’s array and meta_data object. We then pass that data to User component as well as Pagination component. Paginate component receives the only meta_data to process the Pagination component.

Now, save the file, and if you are running npm run watch command, then your JS and CSS have been already compiled. So switch to the browser and type this URL: http://paginate.test/users

Now, you can switch to different pages, and it works fine. It is useful for very basic pagination without any page refresh.

So that is it for Vue Pagination Tutorial From Scratch. Thanks for taking.

Fork Me On Github