Vue Pagination Tutorial: Everything You Need to Know

In this example, 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. Finally, 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, you need to create a Laravel project using the following command.

Step 1: Install Laravel.

If you do not want to use Laravel Valet, 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, 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 set up 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 files using the following command.

npm run dev

Vue Pagination Tutorial From Scratch

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 comes 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 a user and password_resets table.

Step 3: Generate Fake user’s data.

Now, to paginate the data, we need some amount of data. For this example, I am using the faker library to generate the fake users’ data. Then, we use the model factory to create and persist the data in the database. You can see the factory file inside the 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, 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.

  1. UserController(It handles the Laravel view)
  2. 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

Laravel Vue Pagination

In the 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 the front end.

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

Inside the 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 the 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 the 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 the 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 the first ten rows of the data.

Vue Pagination Example

 

So, how can we fetch the other data in the structure of pagination? Laravel provides a URL structure in which you can pass the query string of the 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 it according to that data. So we need to perform the 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)">
                    &laquo;
                </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)">
                    &raquo;
                </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 the parent component called Index.vue file, which sends a network request to the server and fetches the data along with metadata like current_page, last_page, and other properties.

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

I have written that logic by compared that meta_data provided by the 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 calls an API, and fetches 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 the User component as well as the Pagination component. Paginate component receives the only meta_data to process the Pagination component.

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

Pagination in Vue js example tutorial

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

That’s it for this tutorial.

Fork Me On Github

5 thoughts on “Vue Pagination Tutorial: Everything You Need to Know”

  1. Thank you.
    Is it possible to integrate content management for final user?
    For example create posts, edit/delete posts.
    Also im interested to know if there is any online service which could work as CMS for vue application
    I’m just started learning vue

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.