🔄 Integrate DataTables.js with Laravel 12 (Without Yajra): A Complete Step-by-Step Blog

 

Displaying dynamic tables with search, pagination, and sorting is a must-have in modern Laravel applications. While the popular yajra/laravel-datatables package simplifies this task, it may not suit every need. In this blog, we’ll show you how to use DataTables.js in Laravel 12 with a fully custom backend using raw PHP and Eloquent — no external packages like Yajra required.


🧰 What You’ll Learn

  • Setup Laravel project and database
  • Create models, migrations, and dummy data
  • Build a controller with custom server-side AJAX pagination
  • Integrate DataTables.js on the frontend
  • Search, sort, and paginate records without any external Laravel package


🚀 Prerequisites

Make sure you have:

  • PHP 8.1+
  • Composer
  • Laravel 12
  • MySQL or any database
  • Basic Laravel knowledge


📁 Step 1: Create Laravel 12 Project

If you haven't already, create a new Laravel project:

composer create-project laravel/laravel datatable-app cd datatable-app

🔧 Step 2: Create Model and Migration

We will use a Barcode model with relations to a Product.

Run the model and migration:

php artisan make:model Barcode -m php artisan make:model Product -m

database/migrations/xxxx_xx_xx_create_products_table.php

public function up() { Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); $table->timestamps(); }); }

database/migrations/xxxx_xx_xx_create_barcodes_table.php

public function up() { Schema::create('barcodes', function (Blueprint $table) { $table->id(); $table->foreignId('product_id')->constrained()->onDelete('cascade'); $table->string('barcode'); $table->string('barcode_image')->nullable(); $table->timestamps(); }); }

Then run:

php artisan migrate

Seed with dummy data (you can use factories or insert manually).


👨‍💻 Step 3: Define Routes

Open routes/web.php and add:

use App\Http\Controllers\BarcodeController; Route::get('/barcodes', [BarcodeController::class, 'index'])->name('barcodes.index'); Route::get('/barcodes/data', [BarcodeController::class, 'getData'])->name('barcodes.data');

🧠 Step 4: Create Controller with Custom DataTables Response

Generate the controller:

php artisan make:controller BarcodeController

Now use your custom method. Replace the contents of app/Http/Controllers/BarcodeController.php:

namespace App\Http\Controllers; use App\Models\Barcode; use Illuminate\Http\Request; use Carbon\Carbon; class BarcodeController extends Controller { public function index() { return view('barcodes.index'); } public function getData(Request $request) { $columns = [ 0 => 'product_id', 1 => 'barcode', 2 => 'barcode_image', 3 => 'id' ]; $limit = $request->input('length'); $start = $request->input('start'); $order = 'id'; $dir = 'DESC'; if ($request->input('order')) { $order = $columns[$request->input('order.0.column')]; $dir = $request->input('order.0.dir'); } $query = Barcode::with('product')->orderBy($order, $dir); $totalData = $query->count(); $totalFiltered = $totalData; if (!empty($request->input('search.value'))) { $search = $request->input('search.value'); $query = $query->where('barcode', 'LIKE', "%{$search}%"); $totalFiltered = $query->count(); } $barcodes = $query->offset($start)->limit($limit)->get(); $data = []; foreach ($barcodes as $barcode) { $data[] = [ 'id' => $barcode->id, 'product_id' => $barcode->product->name ?? '', 'barcode' => $barcode->barcode, 'barcode_image' => $barcode->barcode_image ?? '', 'created_at' => Carbon::parse($barcode->created_at)->format('Y-m-d'), 'actions' => "<a href='#' class='btn btn-sm btn-danger'>Delete</a>" ]; } return response()->json([ 'draw' => intval($request->input('draw')), 'recordsTotal' => $totalData, 'recordsFiltered' => $totalFiltered, 'data' => $data ]); } }

🖼 Step 5: Create Blade View with DataTable Integration

Create the view at resources/views/barcodes/index.blade.php:

<!DOCTYPE html> <html> <head> <title>Laravel 12 DataTables Without Yajra</title> <link rel="stylesheet" href="https://cdn.datatables.net/1.13.5/css/jquery.dataTables.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"> </head> <body> <div class="container mt-5"> <h2>Barcode List</h2> <table class="table table-bordered" id="barcode-table"> <thead> <tr> <th>Product</th> <th>Barcode</th> <th>Image</th> <th>Created</th> <th>Action</th> </tr> </thead> </table> </div> <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script> <script src="https://cdn.datatables.net/1.13.5/js/jquery.dataTables.min.js"></script> <script> $(function () { $('#barcode-table').DataTable({ processing: true, serverSide: true, ajax: '{{ route('barcodes.data') }}', columns: [ { data: 'product_id', name: 'product_id' }, { data: 'barcode', name: 'barcode' }, { data: 'barcode_image', name: 'barcode_image', render: function(data) { return `<img src="${data}" width="80" height="40">`; }}, { data: 'created_at', name: 'created_at' }, { data: 'actions', name: 'actions', orderable: false, searchable: false } ] }); }); </script> </body> </html>

🔁 How It Works

  • The front-end table calls /barcodes/data using AJAX.
  • Your controller manually handles:

    • Pagination
    • Searching
    • Sorting
  • The result is formatted as JSON as per DataTables spec.

📌 Pros of Not Using Yajra

Feature Advantage
Zero external dependency Pure Laravel & JS
More control Custom query logic
Leaner app Lightweight
Easier debugging All logic visible in controller

🛑 Common Issues

Problem Fix
No data loads Check network tab and browser console
500 server error Check your controller code or route config
Image not displaying Ensure barcode_image_url is a valid path

📁 Final Folder Structure

app/ └── Http/ └── Controllers/ └── BarcodeController.php resources/ └── views/ └── barcodes/ └── index.blade.php routes/ └── web.php database/ └── migrations/ └── create_barcodes_table.php └── create_products_table.php

📌 Conclusion

You now have a complete working example of how to integrate DataTables.js in Laravel 12 with fully custom server-side pagination, search, and sorting — without any external packages like Yajra.

This approach is perfect for those who:

  • Want lightweight apps
  • Prefer custom query logic
  • Don’t want to rely on packages


📦 Bonus Tips

  • Add edit/delete buttons with modals
  • Use buttons extension for export to Excel/PDF
  • Add column filters
  • Lazy-load product name with eager loading


💬 Have Questions?

Let me know in the comments, or reach out if you want the full code in a downloadable ZIP or need help deploying it to production.

Post a Comment

Previous Post Next Post

Contact Form