Skip to content
This repository was archived by the owner on Oct 20, 2025. It is now read-only.
Merged
23 changes: 23 additions & 0 deletions app/app/Http/Controllers/TableController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,29 @@

class TableController
{
public function as(bool $spladeQueryBuilder = false)
{
$query = User::query()->orderBy('name');

$resource = $spladeQueryBuilder ? $query : $query->paginate(10);

$table = SpladeTable::for($resource)
->column('name')
->column('email', as: function ($email, $user) {
if ($email === $user->email) {
return strrev($email);
}
});

if ($spladeQueryBuilder) {
$table->paginate(10);
}

return view('table.users', [
'users' => $table,
]);
}

public function custom(bool $spladeQueryBuilder = false)
{
$query = User::query()->orderBy('name');
Expand Down
1 change: 1 addition & 0 deletions app/routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@

Route::get('/modal', [TableController::class, 'modal'])->name('table.modal');

Route::get('/as/{spladeQueryBuilder?}', [TableController::class, 'as'])->name('table.as');
Route::get('/boolean/{spladeQueryBuilder?}', [TableController::class, 'boolean'])->name('table.boolean');
Route::get('/custom/{spladeQueryBuilder?}', [TableController::class, 'custom'])->name('table.custom');
Route::get('/noPerPage/{spladeQueryBuilder?}', [TableController::class, 'noPerPage'])->name('table.noPerPage');
Expand Down
20 changes: 20 additions & 0 deletions app/tests/Browser/Table/FilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ public function it_can_use_select_filters($url)
});
}

/**
* @test
*
* @dataProvider booleanDataset
*/
public function it_can_provide_a_callback_to_transform_the_value($spladeQueryBuilder)
{
$this->browse(function (Browser $browser) use ($spladeQueryBuilder) {
User::orderBy('name')->first()->forceFill([
'is_admin' => '1',
])->save();

$firstUser = User::query()->orderBy('name')->first();

$browser->visit('/table/as/' . (int) $spladeQueryBuilder)
->assertSeeIn('tr:nth-child(1) td:nth-child(1)', $firstUser->name)
->assertSeeIn('tr:nth-child(1) td:nth-child(2)', strrev($firstUser->email));
});
}

/**
* @test
*
Expand Down
17 changes: 11 additions & 6 deletions lib/Components/Select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ export default {
return this.initChoices(this.element).then(() => {
this.loadRemoteOptions();
});
} else if(this.stack > 0) {
this.element.addEventListener("change", () => {
this.element.blur();
});
}

this.loadRemoteOptions();
Expand Down Expand Up @@ -276,10 +280,9 @@ export default {
if(!this.remoteUrl) {
return;
}

this.loading = true;



Axios({
url: this.remoteUrl,
method: "GET",
Expand All @@ -304,7 +307,8 @@ export default {
destroyChoicesInstance() {
if(this.choices && this.choicesInstance) {
if(this.headlessListener) {
document.querySelector("#headlessui-portal-root")?.removeEventListener("click", this.headlessListener);
document.querySelector("#headlessui-portal-root")?.removeEventListener("click", this.headlessListener, { capture: true });
this.headlessListener = null;
}

if(this.selectChangeListener) {
Expand Down Expand Up @@ -445,10 +449,11 @@ export default {
}

const isActive = vm.choicesInstance.dropdown.isActive;
const isTargeted = vm.choicesInstance.containerOuter.element.contains(e.target);

if(!isActive && e.target === selectElement) {
if(!isActive && isTargeted) {
vm.choicesInstance.showDropdown();
} else if(isActive && e.target !== selectElement) {
} else if(isActive && !isTargeted) {
vm.choicesInstance.hideDropdown();
}
};
Expand Down
8 changes: 7 additions & 1 deletion src/Components/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,13 @@ public function sortBy(Column $column): string
*/
public function getColumnDataFromItem($item, Column $column)
{
return $column->getDataFromItem($item);
$value = $column->getDataFromItem($item);

if (is_callable($as = $column->as)) {
return call_user_func($as, $value, $item);
}

return $value;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/Table/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function __construct(
public Closure|string|null $exportFormat = null,
public Closure|array|null $exportStyling = null,
public array|string|null $classes = null,
public Closure|null $as = null,
) {
if (is_array($classes)) {
$classes = Arr::flatten($classes);
Expand All @@ -53,6 +54,7 @@ public function clone(): static
$this->exportFormat,
$this->exportStyling,
$this->classes,
$this->as,
);
}

Expand Down
2 changes: 2 additions & 0 deletions src/Table/HasColumns.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public function column(
callable|string|null $exportFormat = null,
callable|array|null $exportStyling = null,
array|string|null $classes = null,
callable|null $as = null,
): self {
$key = $key !== null ? $key : Str::kebab($label);
$label = $label !== null ? $label : Str::headline(str_replace('.', ' ', $key));
Expand All @@ -81,6 +82,7 @@ public function column(
exportFormat: $exportFormat,
exportStyling: $exportStyling,
classes: $classes,
as: $as,
))->values();

if (!$searchable) {
Expand Down
14 changes: 9 additions & 5 deletions src/TableExporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,17 @@ public function styles(Worksheet $sheet)
public function map($item): array
{
return $this->columns()->map(function (Column $column) use ($item) {
$exportAs = $column->exportAs;

$value = $column->getDataFromItem($item);

return is_callable($exportAs)
? call_user_func($exportAs, $value, $item, $this->writerType)
: $value;
if (is_callable($exportAs = $column->exportAs)) {
return call_user_func($exportAs, $value, $item, $this->writerType);
}

if (is_callable($as = $column->as)) {
return call_user_func($as, $value, $item);
}

return $value;
})->all();
}

Expand Down