v1.6.0 Release Date: July 2025
v1.7.0 Release Date: July 2025
Status: ✅ Production Ready
Pass any PHP array, plain array, or Laravel Collection directly — Eloquent model not required.
[@livewire](https://github.com/livewire)('aftable', [
'data' => $myArray,
'vars' => ['currency' => 'USD'],
'columns' => [...],
])
vars array is shared across all raw column templates[@aftable](https://github.com/aftable) / [@endaftable](https://github.com/endaftable) Blade DirectivesNew paired directives capture inner HTML to apply your app's custom table styling:
[@aftable](https://github.com/aftable)(['model' => App\Models\User::class, 'columns' => [...]])
<table class="table table-hover my-theme">
<thead class="bg-dark text-white"><tr></tr></thead>
<tbody></tbody>
</table>
[@endaftable](https://github.com/endaftable)
The component extracts <table> tag attributes from your markup and applies them to the rendered table. All standard AF Table features (search, sort, pagination, filters) still work.
raw ColumnsUse PHP closures instead of Blade strings for raw HTML columns — faster (zero Blade overhead), better IDE support, and cleaner syntax:
['key' => 'status', 'label' => 'Status',
'raw' => fn($row) => $row->active
? '<span class="badge bg-success">Active</span>'
: '<span class="badge bg-danger">Inactive</span>'],
// With extra vars
['key' => 'price', 'label' => 'Price',
'raw' => fn($row, $vars) => e($vars['currency']).' '.number_format($row->price, 2)],
customTemplate Mount ParameterPass a <table> HTML string directly to override the table's opening tag — useful when not using the [@aftable](https://github.com/aftable) directive:
[@livewire](https://github.com/livewire)('aftable', [
'model' => App\Models\User::class,
'columns' => [...],
'customTemplate' => '<table class="table table-hover my-theme" id="myTable">',
])
vars Mount ParameterShare variables across all raw column templates:
[@livewire](https://github.com/livewire)('aftable', [
'model' => App\Models\Product::class,
'vars' => ['currency' => 'USD', 'symbol' => '$'],
'columns' => [
['key' => 'price', 'label' => 'Price',
'raw' => '{{ $symbol }}{{ number_format($row->price, 2) }} {{ $currency }}'],
],
])
eval() Removed from getDynamicClass()classCondition in the HasUtilities trait previously used eval() to evaluate class conditions — a significant security risk.
v1.6.0 replacement — no eval(), supports:
fn($row) => $row->activetrue / false'fieldName' → !!$row->fieldName'!fieldName' → !$row->fieldName'field:value' → $row->field === 'value'renderRawHtml() Hardened<?php/?>) from Blade strings automatically\Throwable instead of \Exception to catch all errors| File | Reason |
|---|---|
Core/HasBladeRendering.php |
Unused — rendering moved to DatatableTrait |
Core/HasColumnConfiguration.php |
Unused — columns handled inline |
UI/HasActions.php |
Unused — replaced by actions array handling |
UI/HasBulkActions.php |
Unused |
UI/HasRawTemplates.php |
Unused — raw handled in HasUtilities + DatatableTrait |
UI/HasTemplateRenderer.php |
Unused |
UI/HasUserActions.php |
Unused |
HasUtilities (5 removed): sanitizeHtmlContent, validateJsonPath, validateRelationString, validateExportFormat, sanitizeFilterValue
HasSortingUI (3 removed): getSortIcon, getSortableColumns, getSortState (all shadowed by HasSorting via insteadof)
HasQueryBuilding (7 removed): buildQuery() deprecated stub, query() deprecated stub, applyOptimizedSearch, applyColumnSearch, applyRelationSearch, applyJsonSearch, sanitizeSearch (all overridden by HasUnifiedSearch)
HasQueryOptimization (6+ removed): applyOptimizedSorting, applyOptimizedRelationSorting, applySimpleRelationSubquery, applyNestedRelationSubquery, applyOptimizedColumnSorting (dead chain shadowed by HasQueryBuilding), getTableNameForRelation (had hardcoded airline/airport/flight table map), buildWhereCondition (had hardcoded "flight" check)
The [@AFtable](https://github.com/AFtable) and [@AFtableTrait](https://github.com/AFtableTrait) directives were using the Livewire 2 app('livewire')->mount() API. Updated to \Livewire\Livewire::mount() for Livewire 4 compatibility.
staticVar and extraVars form fieldsgenerateCode() to handle both data modes and extra varsFrom v1.5.2 → v1.6.0:
[@livewire](https://github.com/livewire)('aftable', [...]) usageclassCondition with string expressions that relied on eval(), update them to closures (see classCondition section in COMPLETE_GUIDE.md)[@AFtable](https://github.com/AFtable) / [@AFtableTrait](https://github.com/AFtableTrait) fix is transparent — no syntax changes neededdata, vars, and customTemplate parameters are entirely optionalAftableComponent — Renamed from DatatableTraitThe primary Livewire component has been renamed for clarity and convention alignment:
| Item | Before | After |
|---|---|---|
| PHP class file | DatatableTrait.php |
AftableComponent.php |
| Blade view file | datatable-trait.blade.php |
aftable-component.blade.php |
| Class name | DatatableTrait |
AftableComponent |
| Livewire alias | 'aftable' |
'aftable' (unchanged) |
The old class is kept registered as 'aftable-legacy' for backward compatibility. No change to your Blade files required.
printable: true now opens an isolated pop-up window containing only the table — not the full browser page.
printConfig Array Reference[@livewire](https://github.com/livewire)('aftable', [
'model' => App\Models\User::class,
'columns' => [...],
'printable' => true,
'printConfig' => [
'title' => 'User Report', // shown in print header
'header' => '<p>Confidential</p>',// custom HTML above table
'footer' => 'HR Department', // text/HTML in footer
'fontSize' => 11, // points (default: 11)
'orientation' => 'landscape', // portrait | landscape
'paperSize' => 'A4', // A4 | Letter | Legal | …
'showDate' => true, // print current date in header
'showPageNum' => true, // page number in footer
'tableClass' => 'table-striped', // extra class on printed table
],
])
How it works: Clicking Print creates a new pop-up window (window.open) populated with a clean HTML document containing only the table. Livewire/Alpine attributes are stripped from the DOM clone. window.print() fires automatically after 400 ms.
Requires pop-ups allowed in the browser for the origin.
index.html)The live code generator now has an Output Syntax radio selector:
| Option | Output |
|---|---|
[@livewire](https://github.com/livewire)('aftable', [...]) |
PHP array in a Blade helper (default) |
<livewire:aftable … /> |
Livewire tag syntax with [@php](https://github.com/php) config block |
[@aftable](https://github.com/aftable)([...]) … [@endaftable](https://github.com/endaftable) |
Paired Blade directive with optional custom table |
Two new tabs added to /aftable/test:
| Tab | Demonstrates |
|---|---|
| Custom Template | [@aftable](https://github.com/aftable)/[@endaftable](https://github.com/endaftable) with custom <table class=""> |
| Print Demo | Isolated print window, landscape A4, full printConfig |
TestTraitCommand — All Missing Methods FixedFixed BadMethodCallException on php artisan af-table:test-trait --suite=performance.
Added 14+ methods including:
runQueryBuildingTest(), runColumnManagementTest(), runSearchFilterTest()runPropertyValidationTest() — checks all public properties including printConfigrunPerformanceTests() — real DB benchmarks (page-load, search, sort, distinct values timing against 10K employee rows)runRelationshipTests(), runPerformanceOptimizationTests()displayEnhancedFinalResults() — shows pass/fail table with % score[@livewire](https://github.com/livewire)('aftable', [...]) calls continue to work.printable: true now uses an isolated window instead of window.print() — ensure pop-ups are allowed.printConfig is optional; if omitted, defaults are used (11pt, portrait A4, date shown, no title/footer).
� AftableComponent, Isolated Print, Multi-Syntax Code GeneratorThe primary Livewire component has been renamed from DatatableTrait to AftableComponent (more accurate, follows Laravel/Livewire conventions).
| File | Before | After |
|---|---|---|
| PHP class | DatatableTrait.php | AftableComponent.php |
| Blade view | datatable-trait.blade.php | ftable-component.blade.php |
| Class name | class DatatableTrait extends Component | class AftableComponent extends Component |
| Livewire tag | @livewire('aftable', [...]) | same (no change) |
The old DatatableTrait class is kept as ftable-legacy for backward compatibility:
'php // Still works � 'aftable' now resolves to AftableComponent [@livewire](https://github.com/livewire)('aftable', [...]) <livewire:aftable .../> [@aftable](https://github.com/aftable)([...]) ... [@endaftable](https://github.com/endaftable) '
printable: true now opens an isolated pop-up window containing only the table � not the full browser page.
'php [@livewire](https://github.com/livewire)('aftable', [ 'model' => App\Models\User::class, 'columns' => [...], 'printable' => true, 'printConfig' => [ 'title' => 'User Report', 'header' => '<p>Confidential</p>', // custom HTML above table 'footer' => 'HR Department', // text/HTML below table 'fontSize' => 11, // points (default: 11) 'orientation' => 'landscape', // portrait | landscape 'paperSize' => 'A4', // A4 | Letter | Legal | � 'showDate' => true, // print date in header 'showPageNum' => true, // page number in footer 'tableClass' => 'table-striped', // extra class on printed table ], ]) '
The print window:
Requires pop-ups allowed in the browser for the origin.
The live code generator now has an Output Syntax radio selector:
| Option | Output |
|---|---|
| @livewire('aftable', [...]) | PHP array in a Blade helper (default) |
| <livewire:aftable � /> | Livewire tag syntax with @php config block |
| @aftable([...]) � @endaftable | Paired Blade directive with optional custom table |
Two new tabs on /aftable/test:
| Tab | Purpose |
|---|---|
| Custom Template | Shows @aftable/@endaftable with custom |
| Print Demo | Shows isolated print window with landscape A4 printConfig |
unPerformanceOptimizationTests() � checks optimization methods
How can I help you explore Laravel packages today?