Filament v3 Bulk Actions: Jobs, Progress &amp; Confirmation | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com) [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles  ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

  [ home ](https://www.msaied.com)    [ articles ](https://www.msaied.com/articles)    Filament v3 Table Bulk Actions: Custom Confirmation, Progress Feedback, and Job Dispatch        On this page       1. [  The Problem With Default Bulk Actions ](#the-problem-with-default-bulk-actions)
2. [  1. Custom Confirmation Modal With Extra Fields ](#1-custom-confirmation-modal-with-extra-fields)
3. [  2. Dispatching a Laravel Job Batch ](#2-dispatching-a-laravel-job-batch)
4. [  3. Real-Time Progress Feedback ](#3-real-time-progress-feedback)
5. [  4. Safety Details Worth Getting Right ](#4-safety-details-worth-getting-right)
6. [  Takeaways ](#takeaways)

  ![Filament v3 Table Bulk Actions: Custom Confirmation, Progress Feedback, and Job Dispatch](https://cdn.msaied.com/412/68d290c667a619900211863678fa0b1f.png)

  #filament   #laravel   #queues   #livewire  

 Filament v3 Table Bulk Actions: Custom Confirmation, Progress Feedback, and Job Dispatch 
==========================================================================================

     11 Jul 2026      3 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   The Problem With Default Bulk Actions  ](#the-problem-with-default-bulk-actions)
2. [  02   1. Custom Confirmation Modal With Extra Fields  ](#1-custom-confirmation-modal-with-extra-fields)
3. [  03   2. Dispatching a Laravel Job Batch  ](#2-dispatching-a-laravel-job-batch)
4. [  04   3. Real-Time Progress Feedback  ](#3-real-time-progress-feedback)
5. [  05   4. Safety Details Worth Getting Right  ](#4-safety-details-worth-getting-right)
6. [  06   Takeaways  ](#takeaways)

 The Problem With Default Bulk Actions
-------------------------------------

Filament ships with `DeleteBulkAction` and a handful of helpers, but real applications need bulk actions that:

- Ask for extra input before running (e.g. a reason, a target status)
- Dispatch work to a queue instead of blocking the request
- Show the user meaningful feedback when the batch finishes

This article walks through all three concerns with production-ready code.

---

1. Custom Confirmation Modal With Extra Fields
----------------------------------------------

The `requiresConfirmation()` helper gives you a yes/no dialog. For richer input, swap to `form()` on the action:

```php
BulkAction::make('archive')
    ->label('Archive Selected')
    ->icon('heroicon-o-archive-box')
    ->form([
        Textarea::make('reason')
            ->label('Archive reason')
            ->required()
            ->maxLength(500),
    ])
    ->action(function (Collection $records, array $data): void {
        ArchiveRecordsJob::dispatch(
            $records->modelKeys(),
            $data['reason'],
            auth()->id(),
        );
    })
    ->deselectRecordsAfterCompletion()
    ->successNotificationTitle('Archive queued')
    ->color('warning');

```

The `form()` closure receives validated `$data` alongside `$records`. Filament renders the fields inside the confirmation modal automatically — no custom Livewire component needed.

---

2. Dispatching a Laravel Job Batch
----------------------------------

Passing raw model keys (not Eloquent models) to the job keeps the serialized payload small and avoids stale model state:

```php
// app/Jobs/ArchiveRecordsJob.php
final class ArchiveRecordsJob implements ShouldQueue
{
    use Queueable, Dispatchable, InteractsWithQueue, SerializesModels;

    public function __construct(
        private readonly array $ids,
        private readonly string $reason,
        private readonly int $actorId,
    ) {}

    public function handle(): void
    {
        Post::whereIn('id', $this->ids)
            ->lazyById(200)
            ->each(function (Post $post): void {
                $post->archive($this->reason, $this->actorId);
            });
    }
}

```

For very large selections, split into a **job batch** so each chunk runs independently and failures are isolated:

```php
->action(function (Collection $records, array $data): void {
    $chunks = array_chunk($records->modelKeys(), 100);

    $batch = Bus::batch(
        collect($chunks)->map(
            fn (array $ids) => new ArchiveRecordsJob($ids, $data['reason'], auth()->id())
        )->all()
    )
    ->name('archive-posts-' . now()->timestamp)
    ->allowFailures()
    ->dispatch();

    // Persist batch ID so the UI can poll it
    session()->put('archive_batch_id', $batch->id);
})

```

---

3. Real-Time Progress Feedback
------------------------------

Store the batch ID in the session (or a DB record keyed to the user) and expose a Livewire polling component in your Filament page footer via a render hook:

```php
// AppServiceProvider::boot()
Filament::registerRenderHook(
    PanelsRenderHook::BODY_END,
    fn (): View => view('filament.batch-progress'),
);

```

```xml
{{-- resources/views/filament/batch-progress.blade.php --}}
@if(session('archive_batch_id'))

    @livewire('batch-progress-indicator', [
        'batchId' => session('archive_batch_id')
    ])

@endif

```

The Livewire component calls `Bus::findBatch($this->batchId)` and exposes `$batch->progress()` (0–100) and `$batch->finished()`. When finished, dispatch a browser event to trigger a Filament notification and clear the session key.

---

4. Safety Details Worth Getting Right
-------------------------------------

**Authorization** — always gate the action:

```php
->authorize(fn (): bool => auth()->user()->can('archive', Post::class))

```

**Chunk size** — `lazyById` inside the job prevents loading thousands of models into memory at once. Tune the chunk size to your row width.

**`allowFailures()`** — without this, a single failing job cancels the entire batch. For archiving, partial success is usually acceptable; log failures via `->catch()` on the batch.

**Idempotency** — if a job retries, re-archiving an already-archived post should be a no-op. Guard with a status check at the top of `handle()`.

---

Takeaways
---------

- Use `form()` on `BulkAction` for confirmation modals that collect extra input before dispatch.
- Pass model keys (not models) to queued jobs to keep payloads lean.
- Split large selections into a `Bus::batch()` with `allowFailures()` for resilient processing.
- Persist the batch ID and poll `Bus::findBatch()` in a Livewire component for live progress.
- Always authorize bulk actions explicitly; Filament does not infer policy checks automatically.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Ffilament-v3-table-bulk-actions-custom-confirmation-progress-feedback-and-job-dispatch&text=Filament+v3+Table+Bulk+Actions%3A+Custom+Confirmation%2C+Progress+Feedback%2C+and+Job+Dispatch) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Ffilament-v3-table-bulk-actions-custom-confirmation-progress-feedback-and-job-dispatch) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Can I access the form data inside the bulk action's `action()` closure?        Yes. When you define a `form()` on a BulkAction, Filament injects a validated `array $data` parameter alongside `Collection $records` in the `action()` closure. The keys match the field names you declared in the form. 

      Q02  How do I prevent the bulk action from timing out on very large selections?        Dispatch a queued job (or a Bus batch of jobs) from the action closure instead of processing records inline. The HTTP request returns immediately after dispatch, and the heavy work runs on your queue workers. Use `lazyById()` inside the job to avoid loading all records into memory at once. 

      Q03  Does `deselectRecordsAfterCompletion()` work when the action dispatches a job?        Yes. It deselects the checkboxes on the client side as soon as the action closure returns, regardless of whether the actual work is synchronous or queued. It is purely a UI concern. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://www.msaied.com/articles) 

 [ ![DDD Value Objects and DTOs in Laravel Without the Bloat](https://cdn.msaied.com/450/41688537085b86f102fd8c219a35319f.png) laravel ddd php 

### DDD Value Objects and DTOs in Laravel Without the Bloat

Learn how to implement domain-driven value objects and data transfer objects in Laravel using PHP 8.3 readonly...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 21 Jul 2026     1 min read  

  Read    

 ](https://www.msaied.com/articles/ddd-value-objects-and-dtos-in-laravel-without-the-bloat) [ ![Laravel + Python FastAPI: Image OCR Demo](https://cdn.msaied.com/447/5f3d87146fbf19957973cbc88c6c0155.png) Laravel Python FastAPI 

### Laravel + Python FastAPI: Image OCR Demo

Learn how to call a Python image OCR script from Laravel using FastAPI as the bridge. This premium tutorial wa...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 20 Jul 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-python-fastapi-image-ocr-demo) [ ![Scaffold Laravel Packages with the `laravel package` Command in Installer v5.31.0](https://cdn.msaied.com/449/522e744d3c7bae1f214c179a83ae5b88.png) Laravel Installer Package Development CLI 

### Scaffold Laravel Packages with the `laravel package` Command in Installer v5.31.0

Laravel Installer v5.31.0 introduces a `laravel package` command to scaffold packages from the CLI, automated...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 20 Jul 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/scaffold-laravel-packages-with-the-laravel-package-command-in-installer-v5310) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
