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
Method Position 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 Illuminate Contracts View View ;
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 ),
]);
}
}
The left side of the toolbar contains the search input and filter button:
Appears before the search input:
public function toolbarLeftPrepend () : View | string | null
{
return '<button wire:click="createUser" class="btn btn-primary">+ New User</button>' ;
}
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>' ;
}
The right side of the toolbar contains bulk actions, column visibility, and per-page selector:
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>" ;
}
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
Alert Banner
Action Buttons
Summary Stats
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
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' ;
Use Utility Classes
Leverage your CSS framework’s utility classes: return '<div class="flex items-center gap-2">...</div>' ;
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.