happenv-com/filament-saved-views
Filament Saved Views lets users save their table filters, sorting, and search settings as named views they can switch between. Give your admin panel reusable, per-user views without rebuilding filter state each time.
Install the package with Composer and complete the standard Filament package setup:
composer require happenv-com/filament-saved-views
php artisan vendor:publish --tag="filament-saved-views-migrations"
php artisan migrate
Publish the config if the package exposes one, then review config/filament-saved-views.php for table names, user/tenant scoping, and sharing defaults.
Where to look first:
First use case: add saved views to a Filament table so users can persist filters, sort order, search, and column visibility as named views. After upgrading to v1.8.0, use hasSavableTableState() to avoid offering “Save view” when the table is still in its default state.
Typical first integration:
use Happenv\FilamentSavedViews\Concerns\HasSavedViews; // verify exact namespace in package docs
class ListPosts extends ListRecords
{
use HasSavedViews;
}
Then expose the package’s saved-view action/header component on that table. Start with one high-traffic resource and confirm that saving, loading, and deleting a view works before rolling it out.
Attach saved views at the Filament list-page level, not globally. This keeps the trait close to the table whose state is being persisted and avoids surprising behavior on unrelated pages.
Use hasSavableTableState() in custom UI when you build your own save action:
Action::make('saveView')
->visible(fn (): bool => $this->hasSavableTableState())
->action(fn () => $this->saveCurrentTableView());
Or disable rather than hide it if you want users to understand why saving is unavailable:
->disabled(fn (): bool => ! $this->hasSavableTableState())
Common day-to-day patterns:
hasSavableTableState() inside Livewire action closures or Blade after the table has initialized, not in mount().If the package provides its own save action, check whether v1.8.0 already uses hasSavableTableState() internally. If it does not, wrap or replace the action visibility with the method.
For resources with heavy custom table state, override hasSavableTableState() on the page and add your own checks:
public function hasSavableTableState(): bool
{
return parent::hasSavableTableState()
|| $this->customTableMode !== null;
}
This keeps the save UI aligned with the state your application actually persists.
hasSavableTableState() is a UI helper, not an authorization check. Still enforce who can create, update, or share saved views through policies or package config.tableFilters, tableSort, tableSearch, column toggles) and compare it with what the package persists. A quick dump($this->hasSavableTableState()) inside an action closure usually reveals whether the issue is state detection or UI wiring.How can I help you explore Laravel packages today?