State Persistence
getState() returns a versioned, plain-JSON snapshot of everything the user has set up. setState() puts it back.
localStorage.setItem('chart', JSON.stringify(chart.getState()))
// later, on a fresh chart
chart.setState(JSON.parse(localStorage.getItem('chart')))
The result is JSON-serializable with no functions in it, so it goes into localStorage, a URL, or a database row without special handling.
What is captured
| Theme | The mode, and the preset name |
| Chart type | Candlestick, line, renko, and the rest |
| Indicators | Every active one with its params |
| Zoom | The visible range |
| Drawings | Every anchored shape, mouse-drawn ones included |
| Measurements | Inside drawings, because a measurement is a measure drawing |
| Event markers | meta included |
| Annotations | Lines, bands, points, text |
| Trading price lines | The declarative config |
| Price scale | The mode and its baseline |
| Pane heights | Only the ratios you set |
| Comparison | Mode, benchmark, alignment policy, and each instrument's name and color |
Two things are deliberately not captured
Both are owned by the consumer, so serializing them would either fail or go stale.
Price-line callbacks. onCross, onMove and onRemove are functions and are not serializable. The lines come back; re-bind their callbacks after setState:
chart.setState(saved)
for (const line of chart.getPriceLines()) {
chart.updatePriceLine(line.id, { onCross: handleCross })
}
Comparison instrument data. Your app fetches it, it runs to thousands of bars per instrument, and it would be stale the moment it was written to storage. State carries each instrument's name and color only. setState keeps any instrument still loaded, and emits comparisonRestoreNeeded for the rest:
chart.on('comparisonRestoreNeeded', async ({ names }) => {
for (const name of names) {
chart.addComparison({ name, data: await fetchCloses(name) }) // remembered color is reapplied
}
})
The event does not fire for an instrument whose data is still in memory. Mode, benchmark and alignment policy restore on their own, and a benchmark whose instrument has not come back yet is remembered by name with the primary filling the role until it does.
Versioning and migration
ApexStock.STATE_VERSION // the current schema version
ApexStock.migrateState(oldState) // bring an older snapshot forward
setState() migrates automatically, so an older saved state loads without special handling. Keys are additive and back-filled by migrateState, which means adding a new captured key does not bump the version: a state written before that key existed restores with the default for it.
Custom drawings and unknown presets
Two things depend on what the restoring app has registered:
- A custom drawing type must be registered again with
ApexStock.registerDrawingTool()beforesetStatecan re-render drawings of that type. The registry is global and does not survive a reload on its own. - A theme preset the restoring app does not know falls back to its base mode rather than failing.
See also
- Methods for the full method and event reference
- Comparison Mode for the restore handshake in context
- Drawing Tools for what a drawing record contains