Advanced
State Persistence
Save and restore NuGrid state across sessions.
NuGrid can automatically persist and restore grid state, including column sizes, sorting, filters, and more.
Enabling Persistence
Enable state persistence with the state-persistence prop:
<template>
<NuGrid
:data="data"
:columns="columns"
:state-persistence="{
key: 'my-grid',
storage: 'local',
}"
/>
</template>
Persistence Options
interface StatePersistenceOptions {
key: string
storage: 'local' | 'session' | 'custom'
include?: string[]
exclude?: string[]
debounce?: number
onSave?: (state: any) => void
onLoad?: (state: any) => any
}
Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
key | string | required | Storage key |
storage | 'local' | 'session' | 'custom' | 'local' | Storage type |
include | string[] | All state | State keys to persist |
exclude | string[] | None | State keys to exclude |
debounce | number | 300 | Debounce delay (ms) |
onSave | function | - | Called before saving |
onLoad | function | - | Called after loading |
Persisted State
By default, the following state is persisted:
- Column sizing
- Column ordering
- Column visibility
- Column pinning
- Sorting
- Filters
- Expanded rows (grouping)
- Pagination
Selective Persistence
Persist only specific state:
<template>
<!-- Only persist column sizes and sorting -->
<NuGrid
:data="data"
:columns="columns"
:state-persistence="{
key: 'my-grid',
include: ['columnSizing', 'sorting'],
}"
/>
<!-- Persist everything except filters -->
<NuGrid
:data="data"
:columns="columns"
:state-persistence="{
key: 'my-grid',
exclude: ['columnFilters'],
}"
/>
</template>
Storage Types
Local Storage
Persists across browser sessions:
<template>
<NuGrid
:data="data"
:columns="columns"
:state-persistence="{
key: 'my-grid',
storage: 'local',
}"
/>
</template>
Session Storage
Persists only for the current session:
<template>
<NuGrid
:data="data"
:columns="columns"
:state-persistence="{
key: 'my-grid',
storage: 'session',
}"
/>
</template>
Custom Storage
Use your own storage mechanism:
<script setup lang="ts">
const customStorage = {
getItem: (key: string) => {
// Load from your storage (API, IndexedDB, etc.)
return myCustomStorage.get(key)
},
setItem: (key: string, value: string) => {
// Save to your storage
myCustomStorage.set(key, value)
},
removeItem: (key: string) => {
myCustomStorage.delete(key)
},
}
</script>
<template>
<NuGrid
:data="data"
:columns="columns"
:state-persistence="{
key: 'my-grid',
storage: 'custom',
customStorage,
}"
/>
</template>
Transform State
Modify state before saving or after loading:
<script setup lang="ts">
const persistenceOptions = {
key: 'my-grid',
onSave: (state) => {
// Add metadata
return {
...state,
savedAt: Date.now(),
version: '1.0',
}
},
onLoad: (state) => {
// Migrate old state format
if (!state.version) {
return migrateOldState(state)
}
return state
},
}
</script>
<template>
<NuGrid
:data="data"
:columns="columns"
:state-persistence="persistenceOptions"
/>
</template>
Manual State Management
For full control, manage state manually:
<script setup lang="ts">
const STORAGE_KEY = 'my-grid-state'
// Load state on mount
const savedState = JSON.parse(
localStorage.getItem(STORAGE_KEY) || '{}'
)
const columnSizing = ref(savedState.columnSizing ?? {})
const sorting = ref(savedState.sorting ?? [])
const columnFilters = ref(savedState.columnFilters ?? [])
// Save state on change
watchDebounced(
[columnSizing, sorting, columnFilters],
() => {
localStorage.setItem(STORAGE_KEY, JSON.stringify({
columnSizing: columnSizing.value,
sorting: sorting.value,
columnFilters: columnFilters.value,
}))
},
{ debounce: 500, deep: true }
)
// Reset state
function resetState() {
localStorage.removeItem(STORAGE_KEY)
columnSizing.value = {}
sorting.value = []
columnFilters.value = []
}
</script>
<template>
<div>
<UButton @click="resetState">Reset Layout</UButton>
<NuGrid
v-model:column-sizing="columnSizing"
v-model:sorting="sorting"
v-model:column-filters="columnFilters"
:data="data"
:columns="columns"
/>
</div>
</template>
Reset State
Provide a way to reset persisted state:
<script setup lang="ts">
const gridRef = useTemplateRef('grid')
function resetGridState() {
// Clear storage
localStorage.removeItem('my-grid')
// Reset grid state
gridRef.value?.resetState()
}
</script>
<template>
<div>
<UButton variant="outline" @click="resetGridState">
Reset to Defaults
</UButton>
<NuGrid
ref="grid"
:data="data"
:columns="columns"
:state-persistence="{ key: 'my-grid' }"
/>
</div>
</template>
Per-User State
Store state per user:
<script setup lang="ts">
const user = useAuth().user
const persistenceKey = computed(() =>
`grid-state-${user.value?.id ?? 'anonymous'}`
)
</script>
<template>
<NuGrid
:data="data"
:columns="columns"
:state-persistence="{
key: persistenceKey,
storage: 'local',
}"
/>
</template>
Example: Complete Persistence Setup
<script setup lang="ts">
const gridRef = useTemplateRef('grid')
const toast = useToast()
const persistenceOptions = {
key: 'products-grid',
storage: 'local',
include: ['columnSizing', 'columnOrder', 'sorting', 'columnPinning'],
debounce: 500,
onSave: (state) => {
console.log('Saving state:', state)
return state
},
onLoad: (state) => {
if (state) {
toast.add({
title: 'Layout restored',
color: 'info',
})
}
return state
},
}
function resetLayout() {
localStorage.removeItem('products-grid')
window.location.reload()
}
function exportLayout() {
const state = localStorage.getItem('products-grid')
if (state) {
navigator.clipboard.writeText(state)
toast.add({ title: 'Layout copied', color: 'success' })
}
}
function importLayout() {
const input = prompt('Paste layout JSON:')
if (input) {
try {
JSON.parse(input) // Validate
localStorage.setItem('products-grid', input)
window.location.reload()
} catch {
toast.add({ title: 'Invalid layout', color: 'error' })
}
}
}
</script>
<template>
<div class="space-y-4">
<div class="flex gap-2">
<UButton variant="outline" @click="resetLayout">
Reset Layout
</UButton>
<UButton variant="outline" @click="exportLayout">
Export Layout
</UButton>
<UButton variant="outline" @click="importLayout">
Import Layout
</UButton>
</div>
<NuGrid
ref="grid"
:data="data"
:columns="columns"
:state-persistence="persistenceOptions"
resize-columns
/>
</div>
</template>