Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Dynamic Actions Laravel Package

defstudio/filament-dynamic-actions

Filament Dynamic Actions for Laravel lets you define configurable actions at runtime and attach them to tables, forms, or pages without hardcoding each one, keeping your Filament admin panel flexible, reusable, and easy to extend.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Filament plugin (defstudio/filament-dynamic-actions) that lets you define actions in one place and dispatch them by name from anywhere — Livewire components, Blade, or JS — instead of wiring ->action(fn () => ...) closures at every call site.

Minimal setup:

composer require defstudio/filament-dynamic-actions:^4.0
php artisan vendor:publish --tag="filament-dynamic-actions-config"

Register your named actions in a service provider (or the package's config, depending on version), then attach them to a Filament component with ->dynamicAction('name') and trigger from the frontend.

Where to look first:

  1. The published config file — it holds the action registry and any global guard options.
  2. vendor/defstudio/filament-dynamic-actions/src — the DynamicAction class and the dispatch/validation handler are the two files you'll actually read.
  3. The package tests, which are the most reliable documentation of payload shapes for the current tag.

First use case: a table row action (e.g. delete) declared once with its confirmation modal and authorization, then re-used from a second place (a bulk action, a Blade button, a JS-triggered $dispatch) without duplicating the closure.

Version note for this release: v4.0.6 is a patch — it tightens the validation-check logic that runs on dynamic action dispatches. No API changes listed, so ^4.0 is a safe constraint; you get the fix on composer update with no code edits.

Implementation Patterns

Register once, dispatch by name. The core win is a single registry of named actions:

// config/filament-dynamic-actions.php or a service provider
DynamicAction::make('delete-user')
    ->label('Delete')
    ->icon('heroicon-o-trash')
    ->requiresConfirmation()
    ->action(fn (User $user) => $user->delete());

Then reuse the name across a table action, a page header action, and a Blade-rendered button — all inherit the same label, icon, confirmation, and authorization in one edit.

Payload dispatch with validated params. The 4.0.6 fix affects dispatches that carry parameters: the package now checks the incoming payload against the action's expected signature/schema before invoking it. Prefer typed closures and explicit params over a single array $data bag — you get the validation for free and the failure mode is a clean rejection instead of a TypeError inside your handler.

DynamicAction::make('assign-role')
    ->action(fn (User $user, string $role) => $user->assignRole($role));

Wire it from Livewire with a dispatch carrying the name and params, and from Blade/JS with the package's directive when a full Livewire round-trip isn't needed. Keep the action name as a constant or enum on the PHP side so a rename is a single find-and-replace rather than a silent no-op at runtime.

Compose with authorization, not around it. Put ->visible() / policy checks inside the registered action so every dispatch surface is guarded identically. If you gate at the call site, you'll eventually miss one — and because the action is reachable by name from the frontend, an unguarded registration is a real exposure.

Test the dispatch, not just the closure. A feature test that fires the dynamic dispatch with a valid and an invalid payload covers the code path this release changed, and is the fastest way to catch a regression on future 4.x bumps.

Gotchas and Tips

  • Names are the contract. Dynamic actions are resolved by string at runtime, so a typo or a renamed registration fails silently or throws deep in the dispatcher rather than at compile time. Centralize names (constants/enum) and add a boot-time assertion that every registered name referenced in your views exists.
  • Validation rejections look like nothing happened. If the 4.0.6 payload validation rejects a dispatch, you may get a quiet no-op rather than an exception. When an action "stops firing" after upgrading, log inside the action and confirm the dispatch reaches it at all — check the payload shape first, the handler second.
  • Params are serialized over the wire. Everything crossing a Livewire/JS dispatch is JSON-round-tripped: no closures, no unsaved models by reference, no Collection of Eloquent models with loaded relations. Pass IDs and re-resolve in the action; you get fresh models and avoid stale-state bugs.
  • Modal and confirmation state is per-surface. Two components rendering the same dynamic action each hold their own modal instance. Don't store "which row was selected" on the component and assume the action can read it — pass it in the payload.
  • Debug by isolating the layer. Not firing? (1) Is the name registered and does php artisan about/config cache show it? (2) Does the frontend dispatch carry the right name and params? (3) Does the action's own closure run when invoked directly in tinker? Each answer eliminates one of the three layers.
  • Config caching. The registry frequently lives in config; php artisan config:cache in deploy is fine, but a stale cache across a release is a common "my new action doesn't exist" cause. Clear it in the deploy step.
  • Upgrade cadence. 4.0.5 → 4.0.6 is behavioral only in the dispatch validation path plus CI dependency bumps (actions/checkout 7, esbuild 0.28.1, dependabot/fetch-metadata 3.1.0, ramsey/composer-install 4, git-auto-commit-action 7) — none of those touch your runtime. Run your dispatch tests after the bump; if you relied on loosely-typed payloads being passed through unchecked, tighten the action signature now.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings