AJAX Pagination dengan Laravel dan VueJS


Secara bawaan, Laravel sudah menyertakan jQuery dan VueJS dalam paket instalasinya. Daftar modul NodeJS yang disertakan dapat dilihat pada berkas bootstrap.js dalam direktori resources/assets/js. Berkas bootstrap.js ini dimasukkan (require) ke dalam berkas app.js dalam direktori resources/assets/js, kemudian dikompilasi dan dikumpulkan jadi satu menggunakan Laravel Mix (Webpack) menjadi berkas public/js/app.js.

Selain VueJS dan jQuery, juga terdapat modul NodeJS lain yang dikompilasi, beberapa di antaranya adalah Lodash, Axios dan Bootstrap-Sass. Konfigurasi Laravel Mix sendiri dapat dilihat pada berkas webpack.mix.js pada direktori root.

Laravel Mix untuk Stand-alone Project

Tanpa menginstal modul NodeJS tambahan, kita bisa membuat AJAX pagination di Laravel dengan memanfaatkan VueJS dan Axios, di mana VueJS digunakan untuk memanipulasi data, sedangkan Axios digunakan untuk request data via HTTP.

Sebelum beranjak ke bahasan lebih dalam, ada beberapa hal yang perlu disiapkan, antara lain:

  1. NodeJS dan NPM yang sudah terinstal di mesin lokal.
  2. PHP, Composer dan MySQL.
  3. Pengetahuan dasar akan VueJS dan PHP , framework Laravel khususnya.

Lewati poin satu dan dua jika sudah terbiasa dengan instalasi Laravel dan kompilasi asset menggunakan Laravel Mix.

Instal Laravel Versi 5.4

Pastikan paket instalasi di mesin lokal sesuai dengan requirement instalasi Laravel versi 5.4.

$ composer create-project --prefer-dist laravel/laravel pagination

Ubah pengaturan pada berkas .env sesuai dengan environment lokal. Pastikan juga bahwa konfigurasi pangkalan data sudah benar dan dapat terhubung.

Instal Modul NodeJS

Masuk ke direktori root Laravel dan instal modul NodeJS yang dibutuhkan untuk kompilasi assets.

$ cd pagination
$ npm install

Contoh Data

User merupakan salah satu pre-defined data yang sudah tersedia dalam instalasi Laravel. Kita bisa memanfaatkan data user tersebut untuk contoh kasus pagination yang akan dibuat. Agar data user dapat digunakan, ada beberapa langkah yang harus dijalankan terlebih dahulu.

Menjalankan Migration

Pastikan konfigurasi pangkalan data (database) sudah sesuai pada berkas .env. Buat tabel user dengan menjalankan migrasi dengan perintah berikut.

$ php artisan migrate

Membuat dan Menjalankan Database Seeder

Buat database seeder terlebih dahulu menggunakan perintah berikut.

$ php artisan make:seeder UserTableSeeder

Database seeder ini berfungsi untuk menambahkan data user secara acak menggunakan package Faker.

Dalam method run() pada berkas database/seeds/UserTableSeeder.php, tambahkan potongan skrip di bawah.

<?php
use Illuminate\Database\Seeder;
class UserTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // create 100 users
        $users = factory(\App\User::class, 100)->create();
    }
}

Sebagai informasi, factory untuk user sudah didefinsikan secara bawaan. Skripnya dapat dilihat pada berkas database/factories/ModelFactory.php. Kita juga dimungkinkan untuk membuat factory lain untuk model yang lain. Selengkapnya mengenai factory dapat dibaca pada tautan ini.

Jalankan dabatase seeder menggunakan Artisan dengan perintah:

$ php artisan db:seed --class=UserTableSeeder

Untuk menghasilkan data user lebih banyak, jalankan perintah di atas secara berulang-ulang.

Membuat Controller

Ada dua jenis controller yang akan dibuat. Yang pertama berupa API, di mana controller ini berfungsi untuk memproses kembalian data. Sedangkan controller kedua berfungsi untuk menampilkan view dan manipulasi data melalui view tersebut.

Menambahkan Route

Buka berkas routes/web.php, dan tambahkan dua route yang merujuk pada dua controller yang berbeda.

Route::get('user/index', 'UserController@index');
Route::get('api/user/index', 'Api\UserController@index');

Untuk memastikan route berhasil ditambahkan, kita bisa memeriksanya melalui Artisan.

$ php artisan route:list

Controller API User

Buat controller baru dengan nama UserController dalam direktori app/Http/Controllers/Api. Untuk kemudahan, kita bisa membuatnya menggunakan Artisan console.

$ php artisan make:controller UserController

Tambahkan method index() pada controller tersebut, dan tambahkan pula proses kembalian data user yang sudah berbentuk pagination.

$users = User::orderBy('email', 'ASC')->paginate(20);
return response()->json($users);

Skrip lengkapnya dapat dilihat pada potongan di bawah.

<?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()
    {
    	$users = User::orderBy('email', 'ASC')->paginate(20);

    	return response()->json($users);
    }
}

Apabila diakses secara langsung melalui peramban, maka akan menghasilkan data seperti pada gambar di bawah.

Controller User

Buat lagi sebuah controller baru dengan nama yang sama, yaitu UserController pada direktori berbeda. Letakkan dalam direktori app/Http/Controllers.

$ php artisan make:controller UserController

Seperti yang sudah disinggung sebelumnya, bagian controller ini hanya berfungsi untuk memuat view dan mendefinisikan beberapa variabel, seperti variabel url api user misalnya.

Tambahkan method index() pada controller ini, dan muat berkas view yang akan kita buat nanti.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index()
    {
    	return view('user.index');
    }
}

Membuat dan Menggunakan Template Bawaan

Laravel menyediakan template bawaan berbasis Bootstrap bersamaan dengan Auth. Jadi, posisi selesai diinstal, template ini belum tersedia sebelum kita meng-generate auth Laravel.

$ php artisan make:auth

Apabila perintah di atas berhasil dijalankan, base template dapat dilihat pada direktori resources/views/layouts/app.blade.php.

Membuat View

Skrip lengkap view dapat dilihat dan dipelajari pada media di bawah.

@extends('layouts.app')

@section('content')
<div class="container">
  <div class="row">
    <div class="col-md-12">
      <div class="panel panel-default">
        <div class="panel-heading">Users</div>
        <div class="panel-body">

          <div class="row">
            <div class="col-md-4">
              <!-- pagination links -->	
              <nav v-cloak>
                <ul class="pagination">
                  <li v-if="users.prev_page_url">
                    <a @click.prevent="getUsers(users.prev_page_url)" :href="users.prev_page_url">@lang('pagination.previous')</a>
                  </li>
                  <li v-if="users.next_page_url">
                    <a @click.prevent="getUsers(users.next_page_url)" :href="users.next_page_url">@lang('pagination.next')</a>
                  </li>
                </ul>	
              </nav>
            </div>

            <div class="col-md-8 text-right">
              Display from @{{ users.from }} to @{{ users.to }} of @{{ users.total }} data.
            </div>
          </div>

          <div class="table-responsive">
            <table class="table table-striped" v-cloak>
              <thead>
                <th>Email</th>
                <th>Created</th>
                <th>Updated</th>
                <th>Actions</th>
              </thead>

              <tbody>
                <tr v-for="(user, index) in users.data">
                  <td>@{{ user.email }}</td>
                  <td>@{{ user.created_at }}</td>
                  <td>@{{ user.updated_at }}</td>
                  <td>
                    <button class="btn btn-info btn-xs">Edit</button>
                    <button class="btn btn-danger btn-xs">Delete</button>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>

          <!-- pagination links -->	
          <nav v-cloak>
            <ul class="pagination">
              <li v-if="users.prev_page_url">
                <a @click.prevent="getUsers(users.prev_page_url)" :href="users.prev_page_url">@lang('pagination.previous')</a>
              </li>
              <li v-if="users.next_page_url">
                <a @click.prevent="getUsers(users.next_page_url)" :href="users.next_page_url">@lang('pagination.next')</a>
              </li>
            </ul>	
          </nav>

        </div>	
      </div>
    </div>	
  </div>
</div>

@endsection

Pada view, saya menggunakan beberapa directive seperti v-if untuk memastikan data tidak kosong, serta v-for untuk looping data user yang telah di-request menggunakan script di bawah.

Membuat AJAX Pagination dengan Vue

View sudah dibuat, langkah selanjutnya memanipulasi data menggunakan VueJS dan Axios.

Buka berkas resources/assets/js/app.js. Sebelum menuliskan logika untuk menampilkan data, mari kita lihat terlebih dahulu skrip JS yang ada di dalamnya.

const app = new Vue({
    el: '#app'
});

Dalam berkas tersebut, terdapat sebuah skrip pre-defined untuk instance Vue berbasis elemen #app. Elemen dengan ID app sendiri dapat kita lihat pada base template yang disebutkan di atas. Isian berkas ini perlu dimodifikasi untuk melakukan permintaan data ke controller API user kemudian menampungnya dalam variabel Vue.

Lengkapnya dapat dilihat pada media berikut.

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */

Vue.component('example', require('./components/Example.vue'));

const app = new Vue({
    el: '#app',
    data: {
        api: {
            userIndex: '/api/user/index'
        },
    	users: null
    },

    mounted() {
        console.log('Vue is ready!')
    	// initial user
    	this.getUsers(this.api.userIndex);
    },

    methods: {

    	getUsers(url) {
    		axios.get(url).then(response => {
    			this.users = response.data;
    		}).catch(errors => {
    			console.error(errors);
    		})
    	}
    }
});

Data kembalian yang sudah di-assign ke dalam variable users kemudian digunakan pada view index.blade.php. Semisal, saya menggunakan url next dan prev pada navigasi.

<a @click.prevent="getUsers(users.prev_page_url)" :href="users.prev_page_url">@lang('pagination.previous')</a>

Perhatikan, saya menggunakan simbol @ di depan curly braces agar Laravel tidak mem-parsing-nya sebagai tag PHP.

Mengkompilasi Assets

Skrip di atas belum berfungsi sebelum kita mengkompilasinya ke dalam direktori public/js/app.js.

Lihat juga pada berkas resources/views/layouts/app.blade.php yang mana berkas ini memuat JS dari direktori public/js.

Jalankan perintah di bawah untuk mengkompilasi skrip di atas pada lingkungan produksi (minified & compatibility).

$ npm run production

Untuk kemudahan debugging, kita bisa menggunakan perintah di bawah agar JS hasil kompilasi lebih mudah dibaca.

$ npm run dev

Apabila ingin mengkompilasi assets setiap ada perubahan dan penyimpanan berkas, maka dapat menggunakan perintah berikut.

$ npm run hot

Contoh Aplikasi

Aplikasi jadi contoh kasus di atas dapat dilihat dan diunduh pada repositori berikut.

laravel-id/ajax-pagination

ajax-pagination – Ajax pagination using Vue JS and Axios.

Demo aplikasi dapat dilihat pada tautan berikut.

Untuk Laravel 5.3 ke Bawah

Ada beberapa perbedaan implementasi kasus di atas pada Laravel versi 5.3 ke bawah. Beberapa hal yang berbeda di antaranya adalah:

Request Menggunakan Vue Resource, bukan Axios

Dalam asset JS-nya, Laravel menyertakan Vue Resource untuk request data. Jika pada skrip di atas menggunakan Axios ditulis seperti berikut:

axios.get(url).then(response => {
    this.users = response.data;
}).cactch(error => {
});

Maka dalam Vue Resource dapat ditulis dalam bentuk seperti di bawah.

this.$http.get(url).then(response => {
    this.users = response.body;
}, error => {
});

Laravel Elixir, bukan Laravel Mix

Laravel Elixir menggunakan basis Gulp sebagai task runner-nya. Untuk kompilasi asset, kita bisa menggunakan perintah di bawah.

$ gulp
$ gulp --production
$ gulp watch // hot reloading

Skrip di atas juga dapat dimodifikasi dan ditambahkan fitur lain. Semisal, ketika proses request data user, ditampilkan preloader.

Terakhir, jangan sungkan untuk bertanya apabila mengalami kesulitan memahami bebebrapa skrip di atas. Jangan lupa juga melaporkan bug apabila ada fitur di repositori yang tidak berjalan.

Selamat balajar dan mencoba! 😜

Tak Berkategori

Yugo Purwanto

Pemrogram PHP dan JavaScript yang sedang sibuk mengembangkan aplikasi Glosarium Bahasa Indonesia.

1 comment

Tinggalkan Balasan