yajra/laravel-datatables-html
Laravel DataTables HTML plugin for Laravel: build DataTables markup and initialization scripts in PHP, with Laravel 12+ support and Vite-friendly module output. Works with yajra/laravel-datatables to streamline table configuration and rendering.
composer require yajra/laravel-datatables-html:^13
AppServiceProvider:
use Yajra\DataTables\Html\Builder;
public function boot(): void
{
Builder::useVite();
}
use Yajra\DataTables\Facades\DataTables;
public function index()
{
return DataTables::of(User::query())
->addColumn('action', 'users.action')
->make(true);
}
{!! DataTables::table(['id', 'name', 'email'], 'users') !!}
// Controller
public function users()
{
return DataTables::of(User::query())
->addColumn('action', function($user) {
return '<a href="'.route('users.edit', $user).'">Edit</a>';
})
->rawColumns(['action'])
->make(true);
}
// Blade
{!! DataTables::table(['id', 'name', 'email', 'action'], 'users') !!}
// Controller
public function index()
{
return DataTables::of(User::query())
->editColumn('name', function($user) {
return ucfirst($user->name);
})
->addColumn('status', function($user) {
return $user->active ? '<span class="badge bg-success">Active</span>' : '<span class="badge bg-danger">Inactive</span>';
})
->rawColumns(['status'])
->make(true);
}
public function adminUsers()
{
$columns = ['id', 'name', 'email'];
if (auth()->user()->isSuperAdmin()) {
$columns[] = 'api_token';
}
return DataTables::of(User::query())
->columns($columns)
->make(true);
}
// Livewire Component
public function mount()
{
$this->dataTable = DataTables::of(User::query())
->addColumn('action', 'users.livewire_action')
->make(true);
}
// Blade
<div wire:ignore>
{!! $this->dataTable->table(['id', 'name', 'action'], 'users') !!}
</div>
public function users()
{
return DataTables::of(User::query())
->addButton('bulkDelete', 'Delete Selected', 'post', route('users.bulk'), 'danger')
->addButton('bulkExport', 'Export', 'get', route('users.export'), 'primary')
->make(true);
}
// app/Providers/AppServiceProvider.php
public function boot(): void
{
Builder::useVite();
// Optional: Customize DataTables CSS/JS paths
Builder::setAssetPath('vendor/yajra/datatables-html/resources/assets');
}
// Blade template (resources/views/users/action.blade.php)
<a href="{{ route('users.edit', $user->id) }}" class="btn btn-sm btn-primary">Edit</a>
// Controller
->addColumn('action', 'users.action')
public function editableUsers()
{
return DataTables::of(User::query())
->addColumn('name', function($user) {
return $user->name;
})
->editColumn('name', 'users.name_editor')
->make(true);
}
public function customLayout()
{
return DataTables::of(User::query())
->setTableAttribute('class', 'table-striped')
->setTableAttribute('id', 'custom-users-table')
->make(true);
}
Vite Module Issues
Builder::useVite() is called in AppServiceProvider before any DataTables usage.Uncaught ReferenceError: $ is not defined. Add:
Builder::setScriptPath('https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js');
Raw Columns Not Rendering
rawColumns is escaped.->rawColumns() after adding the column:
->addColumn('action', '<a href="#">Edit</a>')
->rawColumns(['action']);
Livewire Conflicts
wire:ignore on the table and manually trigger updates:
// Custom script
$(document).on('livewire:init', () => {
$.fn.dataTable.isDataTable();
});
Pagination Mismatch
->paginate() or ->simplePaginate() before passing to DataTables:
DataTables::of(User::query()->paginate(10))
Editor Not Saving
->editColumn('name', 'users.name_editor', 'name')
->addEditor('name', 'users.name_editor');
Inspect Generated HTML/JS
Builder::setScriptPath(public_path('vendor/datatables/js'));
Builder::setStylePath(public_path('vendor/datatables/css'));
Enable Query Logging
DataTables::of(User::query()->toBase()->getQuery())
->addColumn('name', function($user) {
\Log::debug($user->toArray());
return $user->name;
});
Check for JavaScript Errors
Builder::setScriptPath()).Custom Templates
// Override default table template
DataTables::of(User::query())
->setTableTemplate('<div class="custom-wrapper">{table}</div>');
Dynamic Column Visibility
->columns(['id', 'name', 'email'])
->visibleIf('email', fn() => auth()->user()->isAdmin());
Conditional Buttons
->addButton('export', 'Export', 'get', route('users.export'))
->addButton('import', 'Import', 'get', route('users.import'))
->visibleIf('import', fn() => auth()->user()->can('import-users'));
Custom Scripts
->addScript(<<<JS
$(document).on('draw.dt', function() {
console.log('Table redrawn!');
});
JS);
Livewire 4+ Compatibility
// For Livewire 4.x
Builder::useLivewire4();
Bootstrap Version Mismatch
Paginator::useBootstrapFive() (or Four) matches your frontend CSS.Vite Asset Paths
Builder::setAssetPath('resources/js/datatables');
Editor Field Types
select2), use:
->addEditor('role', 'users.role_editor')
->field('role')
->field('role_id');
Server-Side Processing
->serverSide() with custom query logic:
->serverSide(function($query) {
$query->where('active', $request->get('active', 1));
});
How can I help you explore Laravel packages today?