Skip to content

Pro Component — This trait requires an Aura UI Pro license.

Overview

The WithAuraBulkActions trait adds multi-row selection and bulk operations to Livewire data table components. It provides individual row checkboxes, a "select all" toggle (including across pages), and a dropdown of configurable bulk actions. Designed to work alongside WithAuraDataTable and the <x-aura::data-table> Blade component.

Installation

Add the trait to your Livewire component:

use BlueStarSystem\AuraUIPro\Traits\WithAuraBulkActions;
use Livewire\Component;

class UserTable extends Component
{
    use WithAuraBulkActions;

    // ...
}

Required Methods

bulkActions(): array

Define the available bulk actions. Each action is an associative array with a key, label, and optional confirmation settings.

public function bulkActions(): array
{
    return [
        [
            'key' => 'delete',
            'label' => 'Delete Selected',
            'confirm' => true,             // Show confirmation dialog before executing
            'confirmMessage' => 'Are you sure you want to delete the selected records?',
            'variant' => 'danger',         // Confirmation dialog variant
        ],
        [
            'key' => 'export',
            'label' => 'Export to CSV',
            'confirm' => false,
        ],
        [
            'key' => 'activate',
            'label' => 'Activate',
            'confirm' => false,
        ],
        [
            'key' => 'deactivate',
            'label' => 'Deactivate',
            'confirm' => true,
            'confirmMessage' => 'Deactivate selected users?',
            'variant' => 'warning',
        ],
    ];
}

You must also implement a handler method for each action key:

public function bulkDelete(): void
{
    User::whereIn('id', $this->selected)->delete();
    $this->clearSelection();
    $this->dispatch('toast', type: 'success', message: count($this->selected) . ' users deleted.');
}

public function bulkExport(): void
{
    // Generate and download CSV
    return $this->exportCsv(User::whereIn('id', $this->selected)->get());
}

public function bulkActivate(): void
{
    User::whereIn('id', $this->selected)->update(['is_active' => true]);
    $this->clearSelection();
    $this->dispatch('toast', type: 'success', message: 'Users activated.');
}

The trait calls the method named bulk + PascalCase of the action key (e.g., delete calls bulkDelete, export calls bulkExport).

Provided Properties

Property Type Default Description
selected array [] Array of selected row IDs.
selectAll bool false Whether all rows on the current page are selected.
selectAllPages bool false Whether all rows across all pages are selected.

Provided Methods

Method Description
toggleSelectAll() Toggle selection of all rows on the current page.
selectAllRecords() Select all records across all pages.
clearSelection() Deselect all rows and reset selection state.
toggleRow(mixed $id) Toggle selection of a single row by ID.
getSelectedCount(): int Returns the count of selected rows.
executeBulkAction(string $key) Trigger a bulk action by its key. Handles confirmation if configured.

Blade Integration

The trait works with <x-aura::data-table> which renders the selection UI automatically. Here is the full Blade pattern:

<!-- resources/views/livewire/user-table.blade.php -->
<div>
    {{-- Bulk action bar (appears when rows are selected) --}}
    @if(count($selected) > 0)
        <div class="mb-4 flex items-center gap-4 rounded-lg bg-indigo-50 px-4 py-3">
            <span class="text-sm font-medium text-indigo-700">
                {{ $this->getSelectedCount() }} selected
            </span>

            <div class="flex gap-2">
                @foreach($this->bulkActions() as $action)
                    <x-aura::button
                        size="sm"
                        :variant="($action['variant'] ?? 'default') === 'danger' ? 'danger' : 'ghost'"
                        wire:click="executeBulkAction('{{ $action['key'] }}')"
                    >
                        {{ $action['label'] }}
                    </x-aura::button>
                @endforeach
            </div>

            <button wire:click="clearSelection" class="ml-auto text-sm text-gray-500 hover:text-gray-700">
                Clear selection
            </button>
        </div>
    @endif

    <x-aura::data-table :columns="$this->columns()" :rows="$this->getRows()">
        <x-slot:header>
            <th class="w-10 px-4 py-3">
                <input
                    type="checkbox"
                    wire:model.live="selectAll"
                    class="rounded border-gray-300"
                />
            </th>
        </x-slot:header>

        @foreach($this->getRows() as $user)
            <tr wire:key="user-{{ $user->id }}">
                <td class="px-4 py-3">
                    <input
                        type="checkbox"
                        value="{{ $user->id }}"
                        wire:model.live="selected"
                        class="rounded border-gray-300"
                    />
                </td>
                <td class="px-4 py-3">{{ $user->name }}</td>
                <td class="px-4 py-3">{{ $user->email }}</td>
                <td class="px-4 py-3">{{ $user->role }}</td>
            </tr>
        @endforeach
    </x-aura::data-table>

    {{-- Select all pages notice --}}
    @if($selectAll && !$selectAllPages)
        <div class="mt-2 text-center text-sm text-gray-500">
            All {{ count($this->getRows()) }} records on this page are selected.
            <button wire:click="selectAllRecords" class="font-medium text-indigo-600 hover:underline">
                Select all {{ $this->getRows()->total() }} records
            </button>
        </div>
    @endif
</div>

Examples

User Management with Bulk Actions

<?php

namespace App\Livewire;

use App\Models\User;
use BlueStarSystem\AuraUIPro\Traits\WithAuraBulkActions;
use BlueStarSystem\AuraUIPro\Traits\WithAuraDataTable;
use Livewire\Component;

class UserTable extends Component
{
    use WithAuraDataTable;
    use WithAuraBulkActions;

    public function columns(): array
    {
        return [
            ['key' => 'name', 'label' => 'Name', 'sortable' => true, 'searchable' => true],
            ['key' => 'email', 'label' => 'Email', 'sortable' => true, 'searchable' => true],
            ['key' => 'role', 'label' => 'Role', 'sortable' => true],
        ];
    }

    public function query(): \Illuminate\Database\Eloquent\Builder
    {
        return User::query();
    }

    public function bulkActions(): array
    {
        return [
            [
                'key' => 'delete',
                'label' => 'Delete',
                'confirm' => true,
                'confirmMessage' => 'Permanently delete the selected users?',
                'variant' => 'danger',
            ],
            [
                'key' => 'export',
                'label' => 'Export CSV',
                'confirm' => false,
            ],
        ];
    }

    public function bulkDelete(): void
    {
        $count = count($this->selected);
        User::whereIn('id', $this->selected)->delete();
        $this->clearSelection();
        $this->dispatch('toast', type: 'success', message: "{$count} users deleted.");
    }

    public function bulkExport(): void
    {
        $users = User::whereIn('id', $this->selected)->get();
        // ... generate CSV and return download response
        $this->clearSelection();
        $this->dispatch('toast', type: 'info', message: 'Export started.');
    }

    public function render()
    {
        return view('livewire.user-table');
    }
}

Order Management with Status Updates

class OrderTable extends Component
{
    use WithAuraDataTable;
    use WithAuraBulkActions;

    public function bulkActions(): array
    {
        return [
            ['key' => 'mark-shipped', 'label' => 'Mark as Shipped', 'confirm' => true,
             'confirmMessage' => 'Mark selected orders as shipped?', 'variant' => 'info'],
            ['key' => 'mark-delivered', 'label' => 'Mark as Delivered', 'confirm' => false],
            ['key' => 'cancel', 'label' => 'Cancel Orders', 'confirm' => true,
             'confirmMessage' => 'Cancel the selected orders? This cannot be undone.', 'variant' => 'danger'],
        ];
    }

    public function bulkMarkShipped(): void
    {
        Order::whereIn('id', $this->selected)
            ->where('status', 'processing')
            ->update(['status' => 'shipped', 'shipped_at' => now()]);

        $this->clearSelection();
        $this->dispatch('toast', type: 'success', message: 'Orders marked as shipped.');
    }

    public function bulkMarkDelivered(): void
    {
        Order::whereIn('id', $this->selected)
            ->where('status', 'shipped')
            ->update(['status' => 'delivered', 'delivered_at' => now()]);

        $this->clearSelection();
        $this->dispatch('toast', type: 'success', message: 'Orders marked as delivered.');
    }

    public function bulkCancel(): void
    {
        $count = Order::whereIn('id', $this->selected)
            ->whereNotIn('status', ['shipped', 'delivered'])
            ->update(['status' => 'cancelled']);

        $this->clearSelection();
        $this->dispatch('toast', type: 'success', message: "{$count} orders cancelled.");
    }
}

Combining All Three Traits

class InvoiceTable extends Component
{
    use WithAuraDataTable;
    use WithAuraFilters;
    use WithAuraBulkActions;

    // All three traits work together seamlessly.
    // Filters narrow down the results.
    // Data table handles sorting, search, pagination.
    // Bulk actions operate on selected rows.
}

Live Demo

27" Monitor Stand Electronics $45.00 Active
Bamboo Cutting Board Home $22.00 Active
Bath Towel Set Home $34.99 Active
Bluetooth Speaker Electronics $42.99 Active
Canvas Sneakers Clothing $44.50 Active
Cargo Pants Clothing $54.99 Active
Ceramic Vase Home $32.99 Active
Clean Code Books $39.99 Active
Cotton T-Shirt Clothing $24.99 Draft
Cycling Gloves Sports $22.50 Active

Accessibility

  • The "select all" checkbox in the header has aria-label="Select all rows on this page".
  • Individual row checkboxes have aria-label="Select row [identifier]".
  • The bulk action bar uses role="toolbar" with aria-label="Bulk actions".
  • Action buttons within the bar have descriptive labels.
  • The "select all pages" link is focusable and announced by screen readers.
  • The selected count is announced via aria-live="polite" when the selection changes.
  • Confirmation dialogs triggered by bulk actions follow the same accessibility patterns as <x-aura::confirmation-dialog>.
  • The "Clear selection" button has aria-label="Clear all selected rows".