PHP code example of developerawam / livewire-datatable
1. Go to this page and download the library: Download developerawam/livewire-datatable library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
developerawam / livewire-datatable example snippets
namespace App\Livewire;
use App\Models\User;
use Livewire\Component;
class UsersTable extends Component
{
public function render()
{
return view('livewire.users-table', [
'model' => User::class,
'columns' => [
'id' => 'ID',
'name' => 'Name',
'email' => 'Email',
'created_at' => 'Joined'
],
'searchable' => ['name', 'email']
]);
}
}
'columns' => [
'id' => 'ID',
'name' => 'Full Name',
'email' => 'Email Address',
'created_at' => 'Joined Date',
'department.name' => 'Department', // Relationship data
]
'searchable' => ['name', 'email', 'department.name']
// In Livewire component
return view('livewire.users-table', [
'model' => User::class,
'columns' => [...],
'searchable' => ['name', 'email'],
'search' => 'john', // auto-applied to table search
]);
// By default, all columns are sortable
// Prevent sorting on specific columns:
'unsortable' => ['actions', 'avatar']
'formatters' => [
'created_at' => 'datetime', // Format as datetime
'updated_at' => 'date', // Format as date
'balance' => 'currency', // Format as currency
'is_active' => 'boolean', // Format as Yes/No
]
'formatters' => [
'description' => [
'type' => 'words',
'options' => ['words' => 10, 'end' => '...']
],
'title' => [
'type' => 'limit',
'options' => ['length' => 50, 'end' => '...']
],
'price' => [
'type' => 'money',
'options' => [
'symbol' => '$',
'decimals' => 2,
'decimal_point' => '.',
'thousand_sep' => ','
]
],
]
'formatters' => [
'name' => [
'type' => 'link',
'options' => [
'route' => 'users.show', // named route
'params' => ['id'], // column names whose values fill the route params
'target' => '_blank', // optional
'text' => 'View Profile', // optional link label (defaults to the cell value)
'class' => 'text-blue-600 hover:underline',
],
],
],
'params' => ['user' => 'id', 'slug' => 'slug'], // route param "user" <- column "id"
'formatters' => [
'name' => [
'type' => 'link',
'options' => [
'url' => 'https://www.google.com/', // static link
],
],
],
'formatters' => [
'name' => [
'type' => 'link',
'options' => [
'url' => '/users/{id}/edit', // {id} replaced with the row's id
],
],
],
// Simple — strip all tags
'formatters' => [
'description' => 'strip', // <b>Hello</b> → Hello
]
// Advanced — allow specific tags
'formatters' => [
'content' => [
'type' => 'strip',
'options' => ['allowed' => '<p><br><b>']
],
]
// Aliases: 'strip', 'html', 'plain' all work the same
'formatters' => [
'bio' => 'html', // <p>Hi</p> → Hi
]
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $with = ['department', 'role'];
public function department()
{
return $this->belongsTo(Department::class);
}
public function role()
{
return $this->belongsTo(Role::class);
}
}
'columns' => [
'id' => 'ID',
'name' => 'Name',
'department.name' => 'Department',
'role.name' => 'Role',
'department.location' => 'Office',
]
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
class User extends Model
{
public function scopeActive(Builder $query): Builder
{
return $query->where('status', 'active');
}
public function scopeFromDepartment(Builder $query, string $department): Builder
{
return $query->whereHas('department', fn ($q) => $q->where('name', $department));
}
}
public function render()
{
return view('livewire.users-table', [
'model' => User::class,
'scope' => 'active', // Single scope
'columns' => [...],
]);
}
public function render()
{
return view('livewire.users-table', [
'model' => User::class,
'scope' => 'fromDepartment',
'scopeParams' => ['Engineering'],
'columns' => [...],
]);
}
public function render()
{
return view('livewire.users-table', [
'model' => User::class,
'columns' => [
'id' => 'ID',
'name' => 'Name',
'status' => 'Status',
'actions' => 'Actions'
],
'customColumns' => [
'status' => 'components.table.status-badge',
'actions' => 'components.table.user-actions'
],
'unsortable' => ['actions']
]);
}
namespace App\Livewire;
use App\Models\User;
use Livewire\Component;
use Livewire\Attributes\On;
class UsersTable extends Component
{
#[On('user-edit')]
public function editUser($id)
{
$this->redirect(route('users.edit', $id));
}
#[On('user-delete')]
public function deleteUser($id)
{
try {
User::findOrFail($id)->delete();
session()->flash('message', 'User deleted successfully!');
// Refresh table after deletion
$this->dispatch('reset-table');
} catch (\Exception $e) {
session()->flash('error', 'Failed to delete user.');
}
}
#[On('user-update-status')]
public function updateUserStatus($id)
{
try {
$user = User::findOrFail($id);
$user->update(['status' => $user->status === 'active' ? 'inactive' : 'active']);
session()->flash('message', 'User status updated!');
// Refresh table after status update
$this->dispatch('reset-table');
} catch (\Exception $e) {
session()->flash('error', 'Failed to update user status.');
}
}
public function render()
{
return view('livewire.users-table', [
'model' => User::class,
'columns' => [...],
'customColumns' => [...],
]);
}
}
// Dispatch event to refresh the table after modifications
$this->dispatch('reset-table');
<livewire:livewire-datatable
:model="User::class"
:columns="[...]"
defaultSortField="created_at"
defaultSortDirection="desc" />
defaultSortField="department.name"
defaultSortDirection="asc"
// config/livewire-datatable.php
return [
'advanced_filter' => true, // Default: true
];
// config/livewire-datatable.php
'theme' => [
'filter_panel' => 'p-4 border-r border-gray-200',
'filter_items' => 'space-y-3',
'filter_input' => 'py-2.5 px-4 border-gray-200 rounded-lg',
'filter_add_button' => 'py-2 px-3 text-sm font-medium',
'filter_reset_button' => 'py-2 px-3 text-sm font-medium',
'filter_apply_button' => 'py-2 px-3 text-sm font-medium',
]
// config/livewire-datatable.php
'session' => [
'enabled' => env('DATATABLE_SESSION', true), // false = disable, closing panel resets again
],
// config/livewire-datatable.php
'advanced_filter' => true, // also enables date filter features
'theme' => [
'date_filter_button' => 'inline-flex items-center gap-x-2 px-3 py-2 text-sm font-medium rounded-sm border ...',
'date_filter_button_icon' => 'size-4',
'date_filter_modal' => 'relative max-w-md w-full mx-4 bg-white dark:bg-gray-800 rounded-sm shadow-xl ...',
'date_filter_header' => 'flex items-center justify-between px-6 py-4 border-b ...',
'date_filter_title' => 'text-lg font-semibold text-gray-900 dark:text-white',
'date_filter_close' => 'inline-flex items-center text-sm font-medium ...',
'date_filter_body' => 'px-6 py-4 space-y-4',
'date_filter_column_label' => 'text-xs font-medium text-gray-500 dark:text-gray-400 mb-1 block',
'date_filter_column_select' => 'w-full py-1.5 px-3 block border border-gray-300 ...',
'date_filter_date_row' => 'flex items-end gap-3',
'date_filter_date_group' => 'flex flex-col flex-1',
'date_filter_date_input' => 'py-1.5 px-3 block border border-gray-300 ...',
'date_filter_date_separator' => 'text-sm text-gray-500 dark:text-gray-400 pb-1.5',
'date_filter_footer' => 'flex items-center justify-end gap-2 px-6 py-4 border-t ...',
'date_filter_apply' => 'py-2 px-4 text-sm font-medium text-white bg-blue-600 rounded-sm ...',
'date_filter_reset' => 'py-2 px-4 text-sm font-medium text-gray-700 ...',
'date_filter_cancel' => 'py-2 px-4 text-sm font-medium text-gray-700 ...',
'date_filter_badge' => 'inline-flex items-center gap-1 px-2 py-1 text-xs font-medium bg-blue-100 ...',
'date_filter_badge_remove' => 'text-blue-600 hover:text-blue-800 ...',
]
'bootstrap_theme' => [
'date_filter_button' => 'btn btn-sm btn-outline-secondary',
'date_filter_button_icon' => '',
'date_filter_modal_backdrop' => 'modal-backdrop fade show',
'date_filter_modal_wrapper' => 'modal d-block',
'date_filter_modal_dialog' => 'modal-dialog modal-dialog-centered',
'date_filter_modal_content' => 'modal-content border shadow',
'date_filter_header' => 'modal-header',
'date_filter_title' => 'modal-title',
'date_filter_close' => 'btn-close',
'date_filter_body' => 'modal-body',
'date_filter_column_label' => 'form-label small text-secondary mb-1',
'date_filter_column_select' => 'form-select',
'date_filter_date_row' => 'd-flex align-items-end gap-3',
'date_filter_date_group' => 'd-flex flex-column flex-fill',
'date_filter_date_input' => 'form-control',
'date_filter_date_separator' => 'text-secondary pb-1 small',
'date_filter_footer' => 'modal-footer',
'date_filter_apply' => 'btn btn-sm btn-primary',
'date_filter_reset' => 'btn btn-sm btn-outline-secondary',
'date_filter_cancel' => 'btn btn-sm btn-secondary',
'date_filter_badge' => 'badge bg-primary bg-opacity-10 text-primary d-inline-flex ...',
'date_filter_badge_remove' => 'btn-close btn-close-sm',
]
namespace App\Livewire;
use Livewire\Component;
class TodoTableApi extends Component
{
public function render()
{
$apiConfig = [
'url' => url('/api/todos'),
'headers' => ['Accept' => 'application/json'],
'data_key' => 'data', // Where to find items
'total_key' => 'total', // Where to find total count
'search_param' => 'search',
'sort_param' => 'sort',
'sort_direction_param' => 'direction',
'per_page_param' => 'per_page',
'page_param' => 'page',
];
return view('livewire.todo-table-api', [
'apiConfig' => $apiConfig,
'columns' => ['id' => 'ID', 'title' => 'Title'],
'searchable' => ['title'],
]);
}
}
$apiConfig = [
'url' => url('/api/todos'),
'method' => 'GET',
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'query_params' => ['status' => 'active'],
'response_key' => 'data.todos', // For nested responses
];
// config/livewire-datatable.php
'export' => [
'enabled' => true,
'types' => ['excel', 'pdf'],
'orientation' => 'portrait',
'paper_size' => 'a4',
'exclude_columns' => [], // exact keys, e.g. ['secret_token', 'user.password']
'exclude_patterns' => ['*_id'], // wildcard via Str::is(), e.g. hides user_id, department.user_id
];
// Mount — only affects export
<livewire:livewire-datatable
:model="User::class"
:columns="$columns"
:excludeColumns="['secret_token', 'department.internal_code']" />
// Component
return view('livewire.users-table', [
'model' => User::class,
'columns' => [...],
'excludeColumns' => ['secret_token'],
]);
'export' => [
'enabled' => true,
'types' => ['excel', 'pdf'],
'orientation' => 'landscape',
'paper_size' => 'a4',
'dropdown' => [
'position' => 'top',
'trigger_text' => 'Download',
],
],
'theme' => [
'custom_export_modal' => 'relative max-w-3xl w-full mx-4 bg-white dark:bg-gray-800 rounded-sm shadow-xl',
'custom_export_header' => 'flex items-center justify-between px-6 py-4 border-b',
'custom_export_title' => 'text-lg font-semibold text-gray-900 dark:text-white',
'custom_export_close' => 'inline-flex items-center text-sm font-medium text-gray-800 cursor-pointer',
'custom_export_body' => 'px-6 py-4 max-h-96 overflow-y-auto',
'custom_export_select_all' => 'flex gap-3 mb-4',
'custom_export_select_all_btn' => 'text-sm font-medium text-blue-600 hover:text-blue-800 cursor-pointer',
'custom_export_deselect_all_btn' => 'text-sm font-medium text-gray-600 hover:text-gray-800 cursor-pointer',
'custom_export_columns' => 'space-y-4',
'custom_export_group' => '',
'custom_export_group_title' => 'text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2',
'custom_export_group_columns' => 'grid grid-cols-2 sm:grid-cols-3 gap-2',
'custom_export_label' => 'inline-flex items-center gap-2 text-sm text-gray-700 cursor-pointer',
'custom_export_checkbox' => 'rounded-sm border-gray-300 text-blue-600 focus:ring-blue-500',
'custom_export_footer' => 'flex items-center justify-between px-6 py-4 border-t',
'custom_export_type_wrapper' => 'flex items-center gap-2',
'custom_export_type_label' => 'text-sm text-gray-600',
'custom_export_type_select' => 'py-1.5 px-3 block border border-gray-300 rounded-sm text-sm w-25',
'custom_export_actions' => 'flex items-center gap-2',
'custom_export_cancel' => 'py-2 px-4 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-sm',
'custom_export_submit' => 'py-2 px-4 text-sm font-medium text-white bg-blue-600 rounded-sm hover:bg-blue-700 disabled:opacity-50',
],
'template' => env('DATATABLE_TEMPLATE', 'tailwind'),
'bootstrap_theme' => [
'wrapper' => 'container-fluid card',
'table' => 'table table-hover table-sm',
'th' => 'table-light',
'th_sort_button' => 'btn btn-sm btn-ghost',
// Custom export modal
'custom_export_backdrop' => 'modal-backdrop fade show',
'custom_export_wrapper' => 'modal d-block',
'custom_export_dialog' => 'modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable',
'custom_export_content' => 'modal-content border shadow',
'custom_export_header' => 'modal-header',
'custom_export_title' => 'modal-title',
'custom_export_close' => 'btn-close',
'custom_export_body' => 'modal-body',
'custom_export_select_all' => 'd-flex gap-2 mb-3',
'custom_export_select_all_btn' => 'btn btn-sm btn-outline-primary',
'custom_export_deselect_all_btn' => 'btn btn-sm btn-outline-secondary',
'custom_export_group_title' => 'text-muted text-uppercase small fw-bold mb-2',
'custom_export_group_columns' => 'row g-2',
'custom_export_checkbox_col' => 'col-6 col-md-4',
'custom_export_checkbox_wrapper' => 'form-check',
'custom_export_checkbox' => 'form-check-input',
'custom_export_label' => 'form-check-label',
'custom_export_footer' => 'modal-footer d-flex justify-content-between',
'custom_export_type_wrapper' => 'd-flex align-items-center gap-2 flex-wrap',
'custom_export_type_label' => 'form-label mb-0 text-nowrap',
'custom_export_type_select' => 'form-select form-select-sm w-auto',
'custom_export_actions' => 'd-flex gap-2',
'custom_export_cancel' => 'btn btn-sm btn-secondary',
'custom_export_submit' => 'btn btn-sm btn-primary',
]
'theme' => [
'table' => 'min-w-full divide-y divide-gray-200',
'th' => 'px-6 py-3 bg-gray-50 text-left text-xs font-medium',
'td' => 'px-6 py-4 whitespace-nowrap text-sm',
'tr' => 'hover:bg-gray-50 transition',
]
'theme' => [
'td_id' => 'font-mono text-gray-500 text-xs',
'td_email' => 'font-medium text-blue-600',
'td_status' => 'text-center font-semibold',
'td_actions' => 'text-right space-x-2',
]
public function render()
{
return view('livewire.users-table', [
'model' => User::class,
'columns' => ['id' => 'ID', 'name' => 'Name'],
'theme' => [
'table' => 'min-w-full divide-y divide-blue-200',
'tr' => 'hover:bg-blue-50',
'td_id' => 'font-mono text-gray-500',
]
]);
}
// config/livewire-datatable.php
'per_page_options' => [10, 25, 50, 100, 'all']
// Set in component
public $perPage = 25;
// config/livewire-datatable.php
'schema_cache_ttl' => env('DATATABLE_SCHEMA_CACHE_TTL', 3600),
namespace App\Livewire;
use App\Models\User;
use Livewire\Component;
use Livewire\Attributes\On;
class AdvancedUsersTable extends Component
{
#[On('user-edit')]
public function editUser($id)
{
$this->redirect(route('users.edit', $id));
}
#[On('user-delete')]
public function deleteUser($id)
{
try {
User::findOrFail($id)->delete();
session()->flash('message', 'User deleted!');
} catch (\Exception $e) {
session()->flash('error', 'Failed to delete user.');
}
}
public function render()
{
return view('livewire.advanced-users-table', [
'model' => User::class,
'scope' => 'active',
'columns' => [
'id' => 'ID',
'name' => 'Name',
'email' => 'Email',
'department.name' => 'Department',
'role.name' => 'Role',
'status' => 'Status',
'created_at' => 'Joined',
'actions' => 'Actions'
],
'searchable' => ['name', 'email'],
'unsortable' => ['actions'],
'customColumns' => [
'status' => 'components.table.status-badge',
'actions' => 'components.table.user-actions'
],
'defaultSortField' => 'created_at',
'defaultSortDirection' => 'desc',
]);
}
}
/*
|--------------------------------------------------------------------------
| Schema Cache TTL (seconds)
|--------------------------------------------------------------------------
*/
'schema_cache_ttl' => env('DATATABLE_SCHEMA_CACHE_TTL', 3600),
protected $with = ['department', 'role'];
js
// tailwind.config.js
module.exports = {
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
"./vendor/developerawam/livewire-datatable/resources/views/*.blade.php",
],
};
bash
php artisan vendor:publish --tag="livewire-datatable-config"
bash
php artisan make:livewire UsersTable
blade
{{-- resources/views/livewire/users-table.blade.php --}}
<div>
<livewire:livewire-datatable
:model="$model"
:columns="$columns"
:searchable="$searchable" />
</div>
blade
@php
$statusColors = [
'active' => 'bg-green-100 text-green-800',
'inactive' => 'bg-red-100 text-red-800',
'pending' => 'bg-yellow-100 text-yellow-800'
];
$colorClass = $statusColors[$value] ?? 'bg-gray-100 text-gray-800';
@endphp
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full {{ $colorClass }}">
{{ ucfirst($value) }}
</span>
blade
<div>
<livewire:livewire-datatable
:api-config="$apiConfig"
:columns="$columns"
:searchable="$searchable" />
</div>
GET /api/todos?search=keyword&sort=title&direction=asc&per_page=10&page=1