harrold-wafo / laravel-custom-datatable
Custom DataTable extension for Laravel Livewire with PDF, Excel and CSV export capabilities
Requires
- php: ^8.0
- barryvdh/laravel-dompdf: ^2.0|^3.0
- laravel/framework: ^8.0|^9.0|^10.0|^11.0
- maatwebsite/excel: ^3.1
- rappasoft/laravel-livewire-tables: ^3.0
README
An elegant and powerful DataTable package for Laravel Livewire, built on top of Rappasoft's Laravel Livewire Tables.
Features
- 🚀 Built on Laravel Livewire Tables
- 📤 Built-in exports (PDF, Excel, CSV)
- 🎨 Theme support with Bootstrap 5 or Tailwind
- 🔄 Automatic bulk actions configuration
- 📱 Responsive tables
- 🌍 Internationalization support
Requirements
- PHP >= 8.1
- Laravel >= 9.0
- Livewire >= 3.0
Installation
composer require harrold-wafo/laravel-custom-datatable
Fast Starting with Export
This package comes with built-in export capabilities requiring minimal setup to get started.
PDF Export
The package includes a generic PDF export view that works out of the box. To use it:
Publish the generic PDF export view:
php artisan vendor:publish --tag=harroldwafo-laravel-datatable-views
Just extend BaseDataTable and your table will automatically have PDF export functionality:
use HarroldWafo\LaravelCustomDatatable\DataTables\BaseDataTable;
class UsersTable extends BaseDataTable {
protected $model = User::class;
// ...existing code...
// Override this to customize column mapping (optional)
protected function customMapAttributes(): array
{
return [
'id' => 'ID',
'name' => 'Name',
'department.name' => 'Department Name', //for relation
'email' => 'Email'
];
}
}
Key methods you can override for PDF export:
- `getPdfView()`: Specify a custom Blade view for PDF rendering
- `customMapAttributes()`: Define which columns appear in the export and their headers, keys should be same as we did in columns definition, and it should also be the same as the model attributes. We can also use relations here.
- `getPdfFormat()`: Set the page format (portrait/landscape)
- `getPdfMargins()`: Customize page margins
- `getExportFileName()`: Set the export file name
### Excel/CSV Export
Excel and CSV exports work automatically without any additional configuration. The package uses a dynamic export class that reads column definitions from your table.
use HarroldWafo\LaravelCustomDatatable\DataTables\BaseDataTable;
class UsersTable extends BaseDataTable {
protected $model = User::class;
// ...existing code...
// Optional: Define custom formatters for Excel/CSV exports
protected function getExportFormatters(): array
{
return [
'created_at' => function($row) {
return $row->created_at->format('Y-m-d');
}
];
}
}
Key methods you can override for Excel/CSV export:
- `getExportClass()`: Define a custom export class (defaults to dynamic export)
- `getExportFileName()`: Set the export file name
- `getExportFormatters()`: Define formatters for specific columns
### Adding Custom Export Formats
You can add additional export formats by:
1. Define a new export method in your table class
2. Add it to the EXPORT_FORMATS constant
class UsersTable extends BaseDataTable {
// Extend the export formats
protected const EXPORT_FORMATS = [
'exportPdf' => 'Export to PDF',
'exportExcel' => 'Export to Excel',
'exportCsv' => 'Export to CSV',
'exportJson' => 'Export to JSON' // Custom format
];
// ...existing code...
// Implement the custom export method
public function exportJson()
{
return $this->handleExport('JSON', function ($records) {
// Custom export logic here
return response()->json($records)
->header('Content-Disposition', 'attachment; filename="' . $this->getFormattedFileName('json') . '"');
});
}
}
## Basic Usage
### 1. Create a Livewire component
php artisan make:livewire UsersTable
Then, update your component:
use App\Models\User; use HarroldWafo\LaravelCustomDatatable\DataTables\BaseDataTable; use Rappasoft\LaravelLivewireTables\Views\Column;
class UsersTable extends BaseDataTable {
protected $model = User::class;
protected const DEFAULT_SORT_FIELD = 'created_at';
protected const DEFAULT_SORT_DIRECTION = 'desc';
public function columns(): array
{
return [
Column::make('ID', 'id')->sortable(),
Column::make('Name', 'name')->sortable()->searchable(),
Column::make('Email', 'email')->sortable()->searchable(),
Column::make('Created At', 'created_at')->sortable()
];
}
protected function getPdfView(): string
{
return 'exports.users-pdf';
}
protected function customMapAttributes(): array
{
return [
'id' => 'ID',
'name' => 'Full Name',
'email' => 'Email Address',
'created_at' => 'Registration Date',
'manager.department' => 'Department' //for relation
];
}
protected function getExportFileName(): string
{
return 'users';
}
}
### 2. Create a PDF View for Export
Create a Blade template for PDF export:
<!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>{{ $title ?? 'Users Export' }}</title>
<style>
body {
font-family: DejaVu Sans, sans-serif;
font-size: 10px;
}
h1 {
text-align: center;
margin-bottom: 20px;
font-size: 18px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 15px;
}
th, td {
border: 1px solid #ddd;
padding: 5px;
text-align: left;
}
th {
background-color: #f2f2f2;
font-weight: bold;
}
</style>
<h1>{{ $title ?? 'Users Export' }} ({{ count($data) }} records)</h1>
<table>
<thead>
<tr>
@foreach($columns as $key => $column)
<th>{{ $column }}</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach($data as $row)
<tr>
@foreach($columns as $key => $column)
<td>{{ $row[$key] ?? '' }}</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
### 3. Use in Blade
## PDF Export Customization
The package provides powerful capabilities for PDF exports. Here are the key methods you can customize:
### Required Methods for PDF Export
#### 1. Defining the PDF View with getPdfView()
You must implement this method to specify which Blade view should render your PDF, or you can just publish export views and it will use by default our exports.generific-pdf view.:
/**
- Get the Blade view used for PDF export, this method will override the default view *
- @return string
*/
protected function getPdfView(): string
{
return 'exports.users-pdf'; // Path to your Blade view
}
Your Blade view will receive these variables:
$columns
: Array of column headers$data
: Array of records formatted for display$title
: Export title (if set)
2. Custom Fields and Headers with customMapAttributes()
Override this method to control which model attributes appear in the PDF export and customize their headers:
/**
* Define custom mapping from model attributes to column headers
* Only attributes defined here will appear in the PDF export
*
* @return array Keys are model attributes, values are column headers
*/
protected function customMapAttributes(): array
{
return [
'id' => 'ID',
'name' => 'Full Name', // 'name' is the model attribute, 'Full Name' is the header
'email' => 'Email Address', // 'email' is the model attribute, 'Email Address' is the header
'created_at' => 'Creation Date' // 'created_at' is the model attribute, 'Creation Date' is the header
];
}
When implementing customMapAttributes()
:
- Only the model attributes specified as keys will be included in the PDF
- The order of attributes in the array determines their order in the PDF
- The values become the column headers in the PDF
Optional PDF Customization Methods
Format and Styling
/**
* Define the PDF page format
*
* @return string
*/
protected function getPdfFormat(): string
{
return PdfConstants::FORMAT_A4_PORTRAIT; // or FORMAT_A4_LANDSCAPE, etc.
}
/**
* Define PDF page margins
*
* @return array
*/
protected function getPdfMargins(): array
{
return [
'margin_top' => 20,
'margin_right' => PdfConstants::MARGIN_RIGHT,
'margin_bottom' => PdfConstants::MARGIN_BOTTOM,
'margin_left' => PdfConstants::MARGIN_LEFT,
];
}
/**
* Get the filename for PDF export
*
* @return string
*/
protected function getExportFileName(): string
{
return 'users-export-' . date('Y-m-d');
}
Data Formatting for Export
You can define formatters to customize how data is displayed in exports:
/**
* Define formatters for exports
*
* @return array
*/
protected function getExportFormatters(): array
{
return [
'created_at' => function($row) {
return $row->created_at->format('M d, Y');
},
'status' => function($row) {
return $row->status ? 'Active' : 'Inactive';
}
];
}
Advanced Examples
Order Table with Conditional Fields
use App\Models\Order;
use HarroldWafo\LaravelCustomDatatable\DataTables\BaseDataTable;
use Rappasoft\LaravelLivewireTables\Views\Column;
class OrdersTable extends BaseDataTable
{
protected $model = Order::class;
protected const DEFAULT_SORT_FIELD = 'created_at';
protected const DEFAULT_SORT_DIRECTION = 'desc';
public function columns(): array
{
return [
Column::make('Order ID', 'id')->sortable(),
Column::make('Reference', 'reference')->sortable()->searchable(),
Column::make('Customer', 'customer_name')->sortable()->searchable(),
Column::make('Total', 'total')->sortable(),
Column::make('Status', 'status')->sortable(),
Column::make('Date', 'created_at')->sortable()
];
}
protected function getPdfView(): string
{
// Different views based on user role
return auth()->user()->hasRole('admin')
? 'exports.orders-admin-pdf'
: 'exports.orders-customer-pdf';
}
protected function customMapAttributes(): array
{
$attributes = [
'reference' => 'Order Reference',
'customer_name' => 'Customer',
'total' => 'Total Amount',
'status' => 'Order Status',
'created_at' => 'Order Date',
];
// Add financial data for admins only
if (auth()->user()->hasRole('admin')) {
$attributes['profit_margin'] = 'Profit Margin (%)';
$attributes['payment_method'] = 'Payment Method';
}
return $attributes;
}
protected function getExportFormatters(): array
{
return [
'total' => function($row) {
return '$' . number_format($row->total, 2);
},
'created_at' => function($row) {
return $row->created_at->format('M d, Y H:i');
},
'status' => function($row) {
$statusClasses = [
'pending' => 'Pending',
'processing' => 'In Process',
'completed' => 'Completed',
'cancelled' => 'Cancelled'
];
return $statusClasses[$row->status] ?? $row->status;
}
];
}
}
Table with Custom PDF Layout
use App\Models\Product;
use HarroldWafo\LaravelCustomDatatable\DataTables\BaseDataTable;
use Rappasoft\LaravelLivewireTables\Views\Column;
use HarroldWafo\LaravelCustomDatatable\Constants\PdfConstants;
class ProductsTable extends BaseDataTable
{
protected $model = Product::class;
protected const DEFAULT_SORT_FIELD = 'name';
protected const DEFAULT_SORT_DIRECTION = 'asc';
public function columns(): array
{
return [
Column::make('ID', 'id')->sortable(),
Column::make('Product', 'name')->sortable()->searchable(),
Column::make('Category', 'category.name')->sortable()->searchable(),
Column::make('Price', 'price')->sortable(),
Column::make('Stock', 'stock')->sortable(),
Column::make('Created', 'created_at')->sortable()
];
}
protected function getPdfView(): string
{
return 'exports.products-pdf';
}
protected function customMapAttributes(): array
{
return [
'id' => 'Product ID',
'name' => 'Product Name',
'category_name' => 'Category',
'price' => 'Retail Price',
'stock' => 'Available Stock',
'description' => 'Description',
];
}
// Custom PDF format (landscape for product catalog)
protected function getPdfFormat(): string
{
return PdfConstants::FORMAT_A4_LANDSCAPE;
}
// Custom PDF margins (smaller for more content)
protected function getPdfMargins(): array
{
return [
'margin_top' => 10,
'margin_right' => 10,
'margin_bottom' => 10,
'margin_left' => 10,
];
}
protected function getExportFormatters(): array
{
return [
'price' => function($row) {
return '$' . number_format($row->price, 2);
},
'category_name' => function($row) {
return $row->category ? $row->category->name : 'Uncategorized';
}
];
}
}
Table Configuration
The BaseDataTable provides default settings that can be overridden:
protected const TABLE_WRAPPER_CLASS = 'table-responsive';
protected const TABLE_CLASS = 'table table-striped table-hover';
protected const THEAD_CLASS = 'table-light';
protected const PER_PAGE_OPTIONS = [10, 25, 50, 100];
protected const DEFAULT_PER_PAGE = 10;
Available Constants
PdfConstants
const FORMAT_A4_LANDSCAPE = 'A4-L';
const FORMAT_A4_PORTRAIT = 'A4';
const MARGIN_TOP = 15;
const MARGIN_RIGHT = 15;
const MARGIN_BOTTOM = 15;
const MARGIN_LEFT = 15;
Publishing Resources
# Publish everything
php artisan vendor:publish --tag=harroldwafo-laravel-datatable-all
# Publish specific components
php artisan vendor:publish --tag=livewire-tables-config
php artisan vendor:publish --tag=harroldwafo-laravel-datatable-translations
php artisan vendor:publish --tag=harroldwafo-laravel-datatable-views
php artisan vendor:publish --tag=harroldwafo-laravel-datatable-theme-axelit
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
The MIT License (MIT). Please see License File for more information.