A view captures a table’s complete query/presentation state: global search, individual search, filters, sort order, column visibility/order, grouping and page size. It does not capture pagination cursors, selections, fetched records or action form values.
Presets
$table->presetViews([
PresetView::make('active')->label('Active')->state([
'filters' => ['status' => 'active'],
'sort' => [['column' => 'created_at', 'direction' => 'desc']],
]),
PresetView::make('archived')->state(['filters' => ['status' => 'archived']])->favorite(false),
]);
Preset IDs are preset:<name>. They are immutable and deploy with your application. Presets default to appearing in the favorites bar; non-favorites remain available in Manage views. Applying a preset merges it over table defaults, never over the previously selected view.
User views
$table->savedViews('tenant:'.$request->user()->tenant_id);
Publish the migration first. The scope is a trusted server-provided value, hashed before storage. Every lookup/write is constrained by user model type, authenticated user ID, scope, and table name. The default scope is global, suitable for a single-tenant application. Guests cannot create or modify views. UUID view IDs are not authorization tokens.
The prebuilt renderer provides a favorites bar, Save current view form, view manager, favorite/unfavorite, replace/rename, and delete controls. Earlier/later controls reorder private views, including their order in the favorites bar. The headless controller exposes the same behavior through reorderViews(ids). “Replace with current” stores the current table state when the named view is saved.
controller.saveView('My open projects', true);
controller.saveView('Renamed view', false, existingId);
controller.favoriteView(existingId, true);
controller.deleteView(existingId);
controller.reorderViews([firstId, secondId]);
controller.defaultView(existingId); // null clears the default
controller.applyView(view);
The default per-user/table/scope limit is 100, configured with spindle-table.max_saved_views. State is validated against the current table schema on save and again when applied. If an application removes a formerly available filter or sort, an old view containing it may fail validation; update/delete affected views during such schema changes. The client never treats stored state as trusted SQL.
The active view ID is represented in URL state. A manual filter/search/column change clears that active marker. The “All” tab restores application defaults. Saved views are private to their owner. The manager can set/clear a per-user default view. It is applied when no explicit state or persisted session state is present. Call persistStateInSession('tenant:'.$tenantId) to retain state across ordinary navigations. Public/shared user views and moderation are not included yet. Code-defined presets can provide shared team tabs without granting users cross-owner writes.