Datatables: Laravel Jetsteam Inertia
Tags: laravel, vue, jetstrea, inertia
Published: 2021-07-26 19:08:31


When I first was trying to set my project using Laravel Jetstream with Inertia and VueJs I spent so much time trying to figure out how to implement jQuery Datatables in my project. In this article I'm going to show you how to do just that step by step.

##Set up your Laravel Project
```
composer create-project laravel/laravel my-crm
```

or via `laravel` command if you have that installed

```
laravel new my-crm
```

Next let's install `Jetstream`

```
composer require laravel/jetstream
```
Install Inertia with Vuejs

```
php artisan jetstream:install inertia
```

Install & build NPM dependencies

```
npm install

npm dev
```
Migrate your database

```
php artisan migrate
```

## Install the amazing datatables laravel package by Yajra
```
composer require yajra/laravel-datatables-oracle:"~9.0"
```

##Install Datatables

```
npm install datatables.net-dt

npm i jquery
```

##Implement Datatables

On your `web.php` routes file, let's add necessary routes to load our resources

```
Route::resource('users', UsersController::class);

Route::name('users.datatables')->get('users', [UsersController::class, 'datatables']);
```

Now, create a `UsersController` and add the following

```
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Inertia\Inertia;

class UsersController extends Controller
{
	/**
	 * Datatable Columns Array
	 *
	 * @var Array
	 */
	private $datatableColumns;

	/**
	 * Datatable Headers Array
	 *
	 * @var Array
	 */
	private $datatableHeaders;

	/**
	 * Datatables Data URL
	 *
	 * @var String
	 */
	private $datatableUrl;

	/**
	 * Controller constructor
	 *
	 * @return void
	 */
	public function __construct() {		
    	$this->datatableHeaders = [
    		'ID', 
    		'Name', 
    		'Email'
    	];

    	$this->datatableColumns = [
			['data' => 'id'],
			['data' => 'name'],
			['data' => 'email']
    	];

    	$this->datatableUrl = route('users.datatables');
	}

	/**
	 * Get datatables JSON Response
	 *
	 * @return \Illuminate\Http\Response
	 */
	public function datatables() {
		$datatables = datatables()
			->of(User::query())
			->addColumn('id', fn($user)	=> $user->id)
			->addColumn('name', fn($user) => $user->name)
			->addColumn('email', fn($user) => $user->email)
			->toArray();

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

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
		return Inertia::render('Users/Index')
			->with('datatableUrl', $this->datatableUrl)
			->with('datatableColumns', $this->datatableColumns)
			->with('datatableHeaders', $this->datatableHeaders);
    }

```

Now that we've got that out of the way, let's build our Vuejs components.

The first component we will be creating is the `Users/Index.vue` component. Inside your `resources/js` folder create a new folder called `Users` and inside this folder create a `.vue` file called `Index.vue`

```
// resources/js/Pages/Users/Index.vue
<template>
		<div class="bg-white rounded-lg shadow-md mx-4 p-6">
                 <!-- we will display our datatable here -->
		</div>

</template>

<script>
	export default {
	
	}
</script>

```

We will get back and change this file later.

Now let's create our `Datatable` component. 

Again inside `resources/js` add a new folder called `Shared` and inside this folder create file called `Datatable.vue`

```
// resources/js/Shared/Datatable.vue

<template>
	<div>
		<table class="table table-hover table-bordered" id="dt-users">
			<thead class="border-1 rounded-sm text-white border-gray-800 bg-gray-900">
				<tr>
					<th v-for="header in headers" :key="header.id">{{ header }}</th>
				</tr>
			</thead>
		</table>
	</div>
</template>

<script>
	import 'jquery/dist/jquery.min.js';
	import "datatables.net-dt/js/dataTables.dataTables"
	import $ from 'jquery'; 

	export default {
		props: ['url', 'columns', 'headers'],
		mounted(){
			let datatable = $('#dt-users').on('processing.dt', function(e, settings, processing) {
			        if (processing) {
			            $('table').addClass('opacity-25');
			        }else {
			            $('table').removeClass('opacity-25');
			        }
			    }).DataTable({
				ajax: {
					url: this.url,
				},
				serverSide: true,
				processing: true,
				paging: true,
				columns: this.columns,
			});

		},
	}
</script>
```
Go back to `resources/js/Pages/Users/Index.vue` and import this file as followed:

```
// final version of resources/js/Users/Index.vue

<template>
	<div class="bg-white rounded-lg shadow-md mx-4 p-6">
		<Datatable 
			:url="datatableUrl" 
			:headers="datatableHeaders"
			:columns="datatableColumns"
		/>
	</div>
</template>

<script>
	import Datatable from '@/Shared/Datatable'

	export default {
		components: {
			Datatable,
		},
		props: ['datatableUrl', 'datatableColumns', 'datatableHeaders'],
	}
</script>
```

And that's it! Leave questions in the comment section.

Happy coding.

Cover image credit [pikisuperstar](https://www.freepik.com/pikisuperstar)