Skip to main content
Toolbar slots allow you to inject custom content into the table’s toolbar area and around the table itself. Each slot can return a Blade view, HTML string, or null.

Available Slots

MethodPosition
toolbarLeftPrepend()Before search input (left side)
toolbarLeftAppend()After search & filter buttons (left side)
toolbarRightPrepend()Before bulk/columns/per-page (right side)
toolbarRightAppend()After per-page selector (right side)
beforeTable()After toolbar, before data rows
afterTable()After data rows, before pagination
Each method returns View|string|null. Return null (default) to render nothing.

Basic Usage

Override the slot methods in your table component:
use IlluminateContractsViewView;

class UsersTable extends DataTableComponent
{
    public function toolbarLeftPrepend(): View|string|null
    {
        return '<button wire:click="createUser" class="lt-btn-primary">+ New User</button>';
    }

    public function toolbarRightAppend(): View|string|null
    {
        return view('tables.partials.toolbar-actions');
    }

    public function beforeTable(): View|string|null
    {
        return '<div class="p-3 bg-yellow-50 text-yellow-800 rounded">⚠ 5 users pending approval</div>';
    }

    public function afterTable(): View|string|null
    {
        return view('tables.partials.summary', [
            'total' => $this->getSelectedCount($this->totalRows ?? 0),
        ]);
    }
}

Toolbar Left Slots

The left side of the toolbar contains the search input and filter button:

toolbarLeftPrepend()

Appears before the search input:
public function toolbarLeftPrepend(): View|string|null
{
    return '<button wire:click="createUser" class="btn btn-primary">+ New User</button>';
}

toolbarLeftAppend()

Appears after the search input and filter button:
public function toolbarLeftAppend(): View|string|null
{
    return '<button wire:click="refresh" class="btn btn-secondary">🔄 Refresh</button>';
}

Toolbar Right Slots

The right side of the toolbar contains bulk actions, column visibility, and per-page selector:

toolbarRightPrepend()

Appears before bulk actions dropdown:
public function toolbarRightPrepend(): View|string|null
{
    $count = User::where('active', false)->count();
    return "<span class='text-red-600 text-sm font-medium'>{$count} inactive</span>";
}

toolbarRightAppend()

Appears after the per-page selector:
public function toolbarRightAppend(): View|string|null
{
    return '<button wire:click="exportAll" class="btn btn-success">Export All</button>';
}

Table Boundary Slots

Inject content immediately before or after the table data rows:

beforeTable()

Appears after the toolbar but before the table rows:
public function beforeTable(): View|string|null
{
    if (! $this->hasActiveFilters()) {
        return null;
    }

    return '<div class="p-2 text-sm text-gray-500">Filters are active. Showing filtered results.</div>';
}

afterTable()

Appears after the table rows but before pagination:
public function afterTable(): View|string|null
{
    return view('tables.partials.summary', [
        'total' => $this->totalRows ?? 0,
    ]);
}

Returning Blade Views

For complex content, return a Blade view:
public function toolbarLeftPrepend(): View|string|null
{
    return view('tables.partials.create-button', [
        'label' => 'New User',
        'action' => 'createUser',
    ]);
}
resources/views/tables/partials/create-button.blade.php
<button wire:click="{{ $action }}" class="lt-btn-primary">
    {{ $label }}
</button>

Conditional Slots

Return null to hide a slot based on conditions:
public function beforeTable(): View|string|null
{
    if (! $this->hasActiveFilters()) {
        return null;
    }

    return '<div class="p-2 text-sm text-gray-500">Filters are active.</div>';
}

Accessing Table State

Slots have access to all table properties and methods:
public function toolbarRightPrepend(): View|string|null
{
    $count = $this->getSelectedCount($this->totalRows ?? 0);
    
    if ($count === 0) {
        return null;
    }
    
    return "<span class='badge'>{$count} selected</span>";
}

Complete Examples

public function beforeTable(): View|string|null
{
    $pendingCount = User::where('status', 'pending')->count();
    
    if ($pendingCount === 0) {
        return null;
    }
    
    return "
        <div class='bg-yellow-50 border border-yellow-200 rounded-lg p-4 mb-4'>
            <div class='flex items-center gap-2'>
                <span class='text-yellow-800 font-semibold'>
                    ⚠ {$pendingCount} users pending approval
                </span>
                <button wire:click='reviewPending' class='btn-sm btn-warning'>
                    Review
                </button>
            </div>
        </div>
    ";
}

Slot Rendering

The resolveSlot() method handles rendering for all slot types:
public function resolveSlot(View|string|null $slot): string
{
    if ($slot === null) {
        return '';
    }

    if ($slot instanceof View) {
        return $slot->render();
    }

    return $slot;
}
You don’t need to call resolveSlot() directly — the table component handles this automatically.

Styling Tips

1

Match Theme Classes

Use your table’s theme classes for consistent styling:
$btnClass = $this->isBootstrap5() 
    ? 'btn btn-primary rounded-3'
    : 'btn btn-primary rounded-lg';
2

Use Utility Classes

Leverage your CSS framework’s utility classes:
return '<div class="flex items-center gap-2">...</div>';
3

Respect Dark Mode

Check $this->darkMode for dark mode support:
$bgClass = $this->darkMode 
    ? 'bg-gray-800 text-gray-200'
    : 'bg-gray-100 text-gray-800';

Best Practices

Return null for empty slots

Don’t return empty strings — return null to avoid rendering empty elements.

Use views for complexity

Move complex HTML to Blade views for better maintainability.

Access table state

Leverage table properties like $this->totalRows and $this->hasActiveFilters().

Check permissions

Guard actions with authorization checks before displaying buttons.

Build docs developers (and LLMs) love