| name | gridlite-views-crud |
| description | View lifecycle: save, load, update, delete, rename, duplicate, default views, storage stats, modified state tracking. Use when implementing view management logic. |
| user-invocable | true |
Gridlite Views CRUD & Lifecycle
View Lifecycle
Save → Load → Modify table → Update (or Save New) → Delete
Each action auto-updates the live query-backed stores. No manual refresh() needed.
Save a New View
const view = await viewStore.actions.save({
name: 'High-value cases',
description: 'Cases with fines over 25k',
config: {
filters: [{ id: 'f1', field: 'fine_amount', operator: 'greater_than', value: 25000 }],
filterLogic: 'and',
sorting: [{ column: 'date', direction: 'desc' }],
grouping: [],
columnVisibility: { id: true, type: true, date: true, fine_amount: true },
columnOrder: ['type', 'date', 'fine_amount', 'organization'],
columnWidths: { organization: 250 },
pageSize: 25
}
});
Load a View
const view = await viewStore.actions.load(viewId);
if (view) {
applyConfigToTable(view.config);
}
Track Modifications
When the user changes filters, sorting, or columns after loading a view:
viewStore.actions.markModified();
Update an Existing View
await viewStore.actions.update(viewId, {
config: captureCurrentConfig()
});
You can update individual fields:
await viewStore.actions.update(viewId, { description: 'Updated description' });
await viewStore.actions.update(viewId, { name: 'Renamed View' });
Delete a View
await viewStore.actions.delete(viewId);
Rename a View
await viewStore.actions.rename(viewId, 'New Name');
Duplicate a View
The duplicate pattern uses nameExists to generate a unique name:
let duplicateName = `${view.name} (Copy)`;
let counter = 2;
while (await viewStore.actions.nameExists(duplicateName)) {
duplicateName = `${view.name} (Copy ${counter})`;
counter++;
}
await viewStore.actions.save({
name: duplicateName,
description: view.description,
config: view.config,
originalQuery: view.originalQuery
});
Default View
Set a view as the default for this grid:
await viewStore.actions.setDefaultView(viewId);
Load the default view on mount:
onMount(async () => {
viewStore = initViewStore(db, 'my-grid');
await viewStore.actions.waitForReady();
const defaultView = await viewStore.actions.loadDefaultView();
if (defaultView) {
applyConfigToTable(defaultView.config);
}
});
Storage Stats
const stats = await viewStore.actions.getStorageStats();
if (stats.count >= stats.limit) {
alert('View limit reached. Delete unused views.');
}
Clear Active View
viewStore.actions.clearActive();
Name Uniqueness Check
const exists = await viewStore.actions.nameExists('My View');
const exists = await viewStore.actions.nameExists('New Name', currentViewId);
SavedView Object Shape
interface SavedView {
id: string;
gridId: string;
name: string;
description?: string;
config: ViewConfig;
originalQuery?: string;
groupId?: string;
isDefault: boolean;
usageCount: number;
lastUsed: string;
createdAt: string;
updatedAt: string;
}
Move a View to a Group
Views can be assigned to groups via the store's groupActions:
await viewStore.groupActions.moveViewToGroup(viewId, groupId);
await viewStore.groupActions.moveViewToGroup(viewId, null);
The groupId field on SavedView updates automatically via live queries. See the store-api skill for full group CRUD documentation.