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 Table Presets Laravel Package

ymsoft/filament-table-presets

A Filament package for saving and restoring table presets—let users store column layouts, filters, sorting, and other table settings, then switch between named views instantly without reconfiguring tables each time.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register the plugin in three steps, then verify with one real table before rolling it out.

composer require ymsoft/filament-table-presets
php artisan vendor:publish --tag="filament-table-presets-config"
php artisan vendor:publish --tag="filament-table-presets-migrations"
php artisan migrate

Then register it on the panel (not globally) so you can gate it per panel/environment:

// app/Providers/Filament/AdminPanelProvider.php
use Ymsoft\FilamentTablePresets\TablePresetsPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugin(TablePresetsPlugin::make());
}

Where to look first. In this order: the README's usage block, src/TablePresetsPlugin.php (what the fluent configure methods actually expose), the published config/filament-table-presets.php (ownership/scoping/storage options), and the migration (the column set tells you what a preset can actually store — usually table identifier, user/tenant id, name, and a JSON state payload). Read the migration before the README; it's the most honest description of what is persisted.

First use case. Pick your widest ListRecords page — a support inbox, orders, or audit log with 15+ columns and several filters. Add the preset action to that page's header and let two or three internal users save a named view ("My open tickets", "Refunds this week"). That single page will surface every configuration question you have (scoping, defaults, column-name churn) in an afternoon. Do not start with the resource your customers use.

Implementation Patterns

Wire it to the page, not the resource. Presets are page state, and the plugin is normally attached at the Livewire page level (via the trait/action the plugin exposes) or through a header action returned from getHeaderActions(). Attaching at the resource level and hoping it cascades to every page (ListRecords, relation managers, dashboard widgets) is the most common mis-step. Add it to ListRecords, confirm it works, then decide about relation managers separately.

Treat it as a wrapper around Filament's own table state. The plugin is fundamentally persisting the same array Filament already builds from column visibility, filters, sort, search, and (depending on config) pagination. Two consequences follow:

  • Anything you add to the table via a custom filter must be serializable. Filters holding closures, models, or uploaded files will either fail to save or restore in a broken state — test each custom filter explicitly.
  • If you also enable Filament's ->persistFiltersInSession(), you now have two persistence layers fighting over the same state. Pick one. Presets are the better choice for anything a user will want to return to next week; session persistence is only for transient in-flow filtering.

Defaults matter more than the save button. The feature people actually feel is "the table opens the way I left it." Expose a per-user default preset (the plugin typically offers a fluent toggle and a way to resolve the default) and apply it on page mount. Without a default, presets become a feature nobody discovers — a dropdown people scroll past.

Seed presets for onboarding. Ship 2–3 system presets per critical resource created via a seeder or a Preset::create([...]) call in your provisioning flow, especially if your app onboards tenants. New users landing on a table with a "Ready to ship", "Needs review" preset already present get value on day one; a blank dropdown does not.

Scope deliberately. Per-user presets are the safe default. Shared/team presets need an authorization story: who can rename, overwrite, or delete a preset another user created? Add a policy on the plugin's model (published config usually lets you swap the model) rather than patching the package. If you're multi-tenant, confirm the preset query is tenanted — a preset leaking across tenants is a real data-disclosure bug, not a cosmetic one.

Version and test it like application code. Presets are user data; a plugin upgrade that changes the stored payload shape will silently break saved views. Write one Livewire test per critical page asserting that mounting with a given preset yields the expected visible columns, and pin the plugin version in composer.json ("ymsoft/filament-table-presets": "~1.0") so a minor bump can't land unreviewed.

Gotchas and Tips

Column renames silently orphan state. If the JSON payload keys on column names (it almost certainly does), renaming amount to total_amount doesn't error — presets just stop restoring that column and users see a view that's quietly wrong. Grep your presets table after any column rename, and prefer stable, non-user-facing column names from the start.

The migration is the #1 first-run failure. Forgetting vendor:publish --tag="filament-table-presets-migrations" in a fresh environment (or in CI) produces a "table not found" that looks like a plugin bug. Add the publish+migrate to your deploy script, not just your local setup docs.

Debug by reading the row, not the UI. When a preset won't restore, select state from <presets_table> where id = ? and compare against a freshly captured state. Nine times out of ten the difference is a filter key that no longer matches a getName() you changed, or a null where the current code expects an array. Then check storage/logs/laravel.log and run php artisan filament:cache-components — stale component caches are a frequent red herring in Filament generally.

Config quirks to check explicitly. Read the published config for: the table/model binding (if you can override the Eloquent model, do it — adding a tenant_id or soft deletes to a vendor model via migration-only is painful), whether pagination and search are included in the saved state (many users are surprised that page 4 is restored), and whether there's a per-panel enable flag. Set the enable flag false in local if you don't want preset rows polluting your dev DB.

Index the presets table. These are read on every table render for the current user. A composite index on (user_id, table_identifier) — add it in your own migration if the package doesn't — keeps list pages fast once you have real users. Watch for an N+1 if the plugin loads presets per row in any relation-manager context.

Extension points beat forks. The usual levers are: swap the model via config, publish and override the action/view, and listen for the package's events (if any) rather than editing vendor/. Only 17 stars and 0 dependents means the package is early — you are likely to be the first person to hit an edge case, so keep your customizations in your own service provider and be prepared to send a PR upstream. If the package turns out to be under-maintained, the fallback is a small trait of your own: capture $this->table->getFilters(), column visibility, and sort into a JSON column, and restore in mount(). That's a ~100 line replacement, so don't let this dependency reach a point where it can't be swapped.

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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log