Vue Pagination Tutorial: Everything You Need to Know

Here are the steps to implement pagination in Vue.js with Laravel.

Step 1: Install Laravel.

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 with the following command.

php artisan serve

If you are using Laravel Valet, 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, 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

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

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.

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. The factory file is inside the database  >>  factories  >>  UserFactory.php.

<?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.

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 the API folder, responsible for the API response)

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 the 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

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 the 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);
    }
}

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 PaginationIn the above image, I have minimized the items so that you can see our object’s whole structure.

So, we have created an API, and now Vue needs to consume it. Laravel’s paginate function gives us the metadata 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>

We must update the app.js file inside the 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'
});

We have created our users-list component.

We need to display this component at this URL: http://paginate.test/users.

So, what we need to do is, 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

The only remaining thing is to fetch and display the data.

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, 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 ExampleHow 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 a new folder called pagination. Inside that folder, create one file called Pagination.vue file.

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>

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>

We get 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

You can switch to different pages, and it works fine. Thus, it is helpful 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.