Membuat Datatable Menggunakan Laravel Dan VueJs - CRUDPRO

Membuat Datatable Menggunakan Laravel Dan VueJs

Artikel ini menjelaskan cara menggunakan laravel dan vuejs untuk membuat tabel data tanpa plugin atau pustaka pihak ketiga.

Fungsi dasar tabel data ini:

  • Pencarian realtime
  • Penyortiran realtime
  • Penomoran real-time sisi server dan sisi client
  • Pilih jumlah baris yang akan ditampilkan
  • Memanipulasi baris

Saya sangat menyadari bahwa ada banyak paket yang dapat digunakan untuk mencapai hal ini. Yang paling terkenal di komunitas Laravel adalah Yajra/laravel-datatables yang dibangun dengan jquery. Namun, tutorial akan menunjukkan kepada Anda bagaimana membangun ini menggunakan VueJS.

Langkah 1:

Penyiapan project dan konfigurasi database

Siapkan project laravel baru yang disebut Datatable atau Selected.

laravel new Datatable
or:
composer create-project --prefer-dist laravel/laravel Datatable

Ubah ke direktori.

cd Datatable

Buat database dengan Phpmyadmin atau SequelProGUI.

Kemudian edit file .env untuk mengatur nama database, pengguna database, dan kata sandi.

DB_DATABASE=datatable
DB_USERNAME=username
DB_PASSWORD=password

Pastikan untuk mengganti nama database, nama pengguna, dan kata sandi sesuai kasusnya.

Jalankan pada command anda :
php artisan config:cache

untuk memperbarui cache dengan perubahan terbaru

Kami hanya akan menggunakan satu file migrasi, yang merupakan migrasi pengguna default yang dikirimkan bersama laravel.

Langkah 2:

File Migrasi dan Seeder:

Buat file UsersTableSeeder.

php artisan make:seeder UsersTableSeeder 

Buka file seeder yang dibuat dan edit sebagai berikut.

<?php
use Illuminate\Database\Seeder;
use App\User;
use Faker\Factory;
class UsersTableSeeder extends Seeder {
public function run() {
   $faker = Factory::create();
    User::truncate();
    foreach(range(1, 100) as $i) {
    User::create([
     'name' => $faker->name,
     'email' => $faker->unique()->email,
     'email_verified_at' => now(),
     'password' => bcrypt('password'),
     'remember_token' => Str::random(10),
   ]);
  }
 }
}

Simpan file, Kemudian buka file DatabaseSeeder.php dan batalkan komentar pada baris berikut.

$this->call(UsersTableSeeder::class);

Simpan semua file dan gunakan seed untuk melakukan migrasi.

php artisan migrate:fresh --seed

Selanjutnya, periksa database, terutama tabel pengguna. Anda akan melihat 100 pengguna acak yang dibuat oleh Cedar.

Langkah 3:

Sertakan Javascript dan CSS dalam file tampilan Anda

Gunakan file tampilan selamat datang default yang disertakan dengan laravel: welcome.blade.php

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<meta name="csrf-token" content="{{ csrf_token() }}">
	<title>Datatable</title>
	<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
</head>
<body>
	<div id="app">
		{{-- This is the vue component --}}
		<all-users></all-users>
	</div>
	<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>

Pastikan itu berisi komponen app.css, app.js, dan Vue yang digunakan oleh <all-users> </ all-users> dan bootstrap cdn.

Langkah 4:

Buat file UsersController.

Buat file UsersController menggunakan:

php artisan make:controller UsersController

Edit file menjadi sama.

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class UsersController extends Controller {
	public function getUsers(Request $request) {
		if ( $request->input('showdata') ) {
			return User::orderBy('created_at', 'desc')->get();
		}
		$columns = ['name', 'email', 'created_at'];
		$length = $request->input('length');
		$column = $request->input('column');
		$search_input = $request->input('search');
		$query = User::select('name', 'email', 'created_at')
		->orderBy($columns[$column]);
		if ($search_input) {
			$query->where(function($query) use ($search_input) {
				$query->where('name', 'like', '%' . $search_input . '%')
				->orWhere('email', 'like', '%' . $search_input . '%')
				->orWhere('created_at', 'like', '%' . $search_input . '%');
			});
		}
		$users = $query->paginate($length);
		return ['data' => $users];
	}
	public function deleteUser(User $user) {
		if($user) {
			$user->delete();
		}
		return 'user deleted';
	}
}

Dari kode di atas, Anda juga bisa mendapatkan semua pengguna di database dan memfilter dan menghapus pengguna.

Langkah 5:

Edit file web.php.

<?php
Route::get('/', function () {
	return view('welcome');
});
Route::get('/users', 'UsersController@getUsers');
Route::delete('/users/{user}/delete', 'UsersController@deleteUser');<?php
Route::get('/', function () {
	return view('welcome');
});
Route::get('/users', 'UsersController@getUsers');
Route::delete('/users/{user}/delete', 'UsersController@deleteUser');

Langkah 6:

Edit file app.js.

require('./bootstrap');
window.Vue = require('vue');
Vue.component('all-users', require('./components/AllUsers.vue').default);
import swal from 'sweetalert2';
window.swal = swal;
window.Fire = new Vue();
const app = new Vue({
el: '#app'
});

Sweetalert2 digunakan untuk notifikasi Ini akan dipasang nanti.

Langkah 7:

Buat file VueJS

Beri nama file AllUsers.vue karena ini adalah nama yang Anda definisikan di file app.js dan digunakan di welcome.blade.php. Perhatikan bahwa file ini harus dibuat pada path: /resources/js/components.

File harus sama dengan:

<template>
	<div class="users-style">
		<div style="margin-bottom: 20px;">
			<h2>Laravel and VueJS Datatable from Scratch</h2>
		</div>
		<div class="table-style">
			<input class="input" type="text" v-model="search" placeholder="Search..."
			@input="resetPagination()" style="width: 250px;">
			<div class="control">
				<div class="select">
					<select v-model="length" @change="resetPagination()">
						<option value="10">10</option>
						<option value="20">20</option>
						<option value="30">30</option>
					</select>
				</div>
			</div>
		</div>
		<table class="table table-bordered table-responsive">
			<thead>
				<tr>
					<th v-for="column in columns" :key="column.name" @click="sortBy(column.name)"
					:class="sortKey === column.name ? (sortOrders[column.name] > 0 ? 'sorting_asc' : 'sorting_desc') : 'sorting'"
					style="width: 40%; cursor:pointer;">
					{{column.label}}
				</th>
				<th>Actions</th>
			</tr>
		</thead>
		<tbody>
			<tr v-for="user in paginatedUsers" :key="user.id">
				<td>{{user.name}}</td>
				<td>{{user.email}}</td>
				<td>{{user.created_at}}</td>
				<td>
					<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
					</a>
					<div class="dropdown-menu">
						<a class="dropdown-item text-primary" href="#" @click="deleteUser(user.id)">Delete User</a>
					</div>
				</td>
			</tr>
		</tbody>
	</table>
	<div>
		<nav class="pagination" v-if="!tableShow.showdata">
			<span class="page-stats">{{pagination.from}} - {{pagination.to}} of {{pagination.total}}</span>
			<a v-if="pagination.prevPageUrl" class="btn btn-sm btn-primary pagination-previous" @click="--pagination.currentPage"> Prev </a>
			<a class="btn btn-sm btn-primary pagination-previous" v-else disabled> Prev </a>
			<a v-if="pagination.nextPageUrl" class="btn btn-sm pagination-next" @click="++pagination.currentPage"> Next </a>
			<a class="btn btn-sm btn-primary pagination-next" v-else disabled> Next </a>
		</nav>
		<nav class="pagination" v-else>
			<span class="page-stats">
				{{pagination.from}} - {{pagination.to}} of {{filteredUsers.length}}
				<span v-if="`filteredUsers.length < pagination.total`"></span>
			</span>
			<a v-if="pagination.prevPage" class="btn btn-sm btn-primary pagination-previous" @click="--pagination.currentPage"> Prev </a>
			<a class="btn btn-sm pagination-previous btn-primary" v-else disabled> Prev </a>
			<a v-if="pagination.nextPage" class="btn btn-sm btn-primary pagination-next" @click="++pagination.currentPage"> Next </a>
			<a class="btn btn-sm pagination-next btn-primary"  v-else disabled> Next </a>
		</nav>
	</div>
</div>
</template>
<script>
	export default {
		created() {
			this.getUsers();
			Fire.$on('reloadUsers', () => {
				this.getUsers();
			})
		},
		data() {
			let sortOrders = {};
			let columns = [
			{label: 'Name', name: 'name' },
			{label: 'Email', name: 'email'},
			{label: 'Date Added', name: 'created_at'},
			];
			columns.forEach((column) => {
				sortOrders[column.name] = -1;
			});
			return {
				users: [],
				columns: columns,
				sortKey: 'created_at',
				sortOrders: sortOrders,
				length: 10,
				search: '',
				tableShow: {
					showdata: true,
				},
				pagination: {
					currentPage: 1,
					total: '',
					nextPage: '',
					prevPage: '',
					from: '',
					to: ''
				},
			}
		},
		methods: {
			deleteUser(id) {
				axios.delete(`/users/${id}/delete`).then(() => {
					Fire.$emit('reloadUsers')
					swal(
						'Success!',
						'User deleted',
						'success'
						)
				}).catch(() => {
					swal('Failed', 'There was something wrong', 'warning');
				});
			},
			getUsers() {
				axios.get('/users/', {params: this.tableShow})
				.then(response => {
					console.log('The data: ', response.data)
					this.users = response.data;
					this.pagination.total = this.users.length;
				})
				.catch(errors => {
					console.log(errors);
				});
			},
			paginate(array, length, pageNumber) {
				this.pagination.from = array.length ? ((pageNumber - 1) * length) + 1 : ' ';
				this.pagination.to = pageNumber * length > array.length ? array.length : pageNumber * length;
				this.pagination.prevPage = pageNumber > 1 ? pageNumber : '';
				this.pagination.nextPage = array.length > this.pagination.to ? pageNumber + 1 : '';
				return array.slice((pageNumber - 1) * length, pageNumber * length);
			},
			resetPagination() {
				this.pagination.currentPage = 1;
				this.pagination.prevPage = '';
				this.pagination.nextPage = '';
			},
			sortBy(key) {
				this.resetPagination();
				this.sortKey = key;
				this.sortOrders[key] = this.sortOrders[key] * -1;
			},
			getIndex(array, key, value) {
				return array.findIndex(i => i[key] == value)
			},
		},
		computed: {
			filteredUsers() {
				let users = this.users;
				if (this.search) {
					users = users.filter((row) => {
						return Object.keys(row).some((key) => {
							return String(row[key]).toLowerCase().indexOf(this.search.toLowerCase()) > -1;
						})
					});
				}
				let sortKey = this.sortKey;
				let order = this.sortOrders[sortKey] || 1;
				if (sortKey) {
					users = users.slice().sort((a, b) => {
						let index = this.getIndex(this.columns, 'name', sortKey);
						a = String(a[sortKey]).toLowerCase();
						b = String(b[sortKey]).toLowerCase();
						if (this.columns[index].type && this.columns[index].type === 'date') {
							return (a === b ? 0 : new Date(a).getTime() > new Date(b).getTime() ? 1 : -1) * order;
						} else if (this.columns[index].type && this.columns[index].type === 'number') {
							return (+a === +b ? 0 : +a > +b ? 1 : -1) * order;
						} else {
							return (a === b ? 0 : a > b ? 1 : -1) * order;
						}
					});
				}
				return users;
			},
			paginatedUsers() {
				return this.paginate(this.filteredUsers, this.length, this.pagination.currentPage);
			}
		}
	};
</script>

Langkah 8:

Edit file app.scss.

.users-style {
width: 70%;
margin: auto;
margin-top: 20px;
.table-style {
margin-bottom: 10px;
input {
width: 175px;
}
.control {
float: right;
}
}
.table {
width: 100%;
.sorting {
background-image: url('/images/sort_both.png');
background-repeat: no-repeat;
background-position: center right;
}
.sorting_asc {
background-image: url('/images/sort_asc.png');
background-repeat: no-repeat;
background-position: center right;
}
.sorting_desc {
background-image: url('/images/sort_desc.png');
background-repeat: no-repeat;
background-position: center right;
}
}
nav a {
color: white!important;
margin-right: 10px;
}
}
h1 {
text-align: center;
font-size: 30px;
}
.pagination {
justify-content: flex-end !important;
.page-stats {
align-items: center;
margin-right: 5px;
}
i {
color: #3273dc !important;
}
}

Langkah 9:

Instal dependensi npm.

npm install

Ingatlah untuk menggunakan sweetalert2 di atas. Instal menggunakan:

npm install sweetalert2 --save

Sangat penting: Untuk mengkompilasi kode javascript, jalankan perintah berikut:

npm run dev

Langkah 10:

Sajikan aplikasi laravel dan buka di browser Anda menggunakan:

php artisan serve

Kemudian buka http://127.0.0.1:8000 dan pastikan aplikasi Anda berjalan. Dengan 100 pengguna yang dibuat secara acak.

Untuk mengedit lebih lanjut file javascript, gunakan watcher dan kompilasi secara real time menggunakan npm runwatch.

Semoga Anda tidak mengalami masalah setelah tutorial ini. Jika demikian, jangan ragu untuk berkomentar karena saya akan segera merespons. Dapatkan kodenya di sini: github

Anda telah melihat Datatable dasar dalam tutorial ini. Ini dapat digunakan secara harfiah dalam situasi apa pun, termasuk menampilkan data dalam bentuk tabel. Anda dapat menjalankannya di SuperAdmin atau merender data yang dipilih.

Terima kasih telah membaca.