You’ve build a marvellous app, configured your layout and the user arranged things just the way he likes. Great!
But the next time he opens the app he wants to find everything just the way he left it. Or (if you’re feeling fancy) choose from a number of saved layouts.
Strelit Layout offers a powerful persistence mechanism for that. Not only every aspect of the layout, also the state of the components within it can be converted into a serialisable object that can be saved to a database, to local storage or wherever else your heart desires.
Here’s how it works:
Creating the Layout
For this tutorial we'll use the layout created in getting-started.
const config = {
root: {
type: 'row',
content: [
{
type: 'component',
componentType: 'testComponent',
componentState: { label: 'A' },
},
{
type: 'column',
content: [
{
type: 'component',
componentType: 'testComponent',
componentState: { label: 'B' },
},
{
type: 'component',
componentType: 'testComponent',
componentState: { label: 'C' },
},
],
},
],
},
};
Initialize your layout on the viewport element:
const containerEl = document.getElementById('layoutContainer');
const myLayout = new StrelitLayout(containerEl);
Listening for State Changes
Your layout instance and all items within it emit events. The event we're interested in is
called
stateChanged. It is emitted whenever an interaction modifies the saveable layout
state (e.g., resizing panes, docking or closing tabs).
myLayout.on('stateChanged', () => {
// Save serialized layout state
const state = myLayout.saveLayout();
localStorage.setItem('savedState', JSON.stringify(state));
});
The layout state is serialized into a clean, JSON-compatible object by calling
myLayout.saveLayout() (note: toConfig() is maintained as an alias).
Serialising entire layouts can be compute-intensive during rapid splitter drags. In production,
debounce your stateChanged listener or trigger saves on explicit user actions.
Creating Layouts from Saved States
When a user returns to the application, check localStorage for a previously saved configuration.
Since saveLayout() outputs aResolvedLayoutConfig
(with calculated numeric sizes), use the built-in helper
createLayoutConfigFromResolved() to convert the snapshot back into a valid
LayoutConfig before passing it to loadLayout():
import { StrelitLayout, createLayoutConfigFromResolved } from 'strelit-ui-kit';
const savedState = localStorage.getItem('savedState');
const initialConfig = savedState
? createLayoutConfigFromResolved(JSON.parse(savedState))
: defaultConfig;
// Load configuration into the layout instance
myLayout.loadLayout(initialConfig);
Saving Component States with stateRequestEvent
While Strelit automatically serializes tree structure, dimensions, and active tabs,
component-specific data (such as form inputs, filters, or cursor positions) is requested
dynamically when saveLayout() runs.
Instead of imperative state calls, assign a callback function to
container.stateRequestEvent. When Strelit serializes the layout tree, it executes
this callback to retrieve your component’s up-to-date state:
myLayout.registerComponentFactoryFunction('testComponent', (container, itemConfig) => {
// Read initial state (either from default config or restored session)
const state = itemConfig.componentState || { label: '' };
// Create native input element
const input = document.createElement('input');
input.type = 'text';
input.value = state.label || '';
input.placeholder = 'Type something to persist...';
// Mount to container element
container.element.appendChild(input);
// Register state serialization provider
container.stateRequestEvent = () => {
return {
label: input.value,
};
};
// Optional: Notify layout on immediate change so stateChanged fires
input.addEventListener('input', () => {
myLayout.emitBaseBubblingEvent('stateChanged');
});
});
The Result
Interactive Example: Saving State
Inspect, fork, and test this complete layout implementation live on CodePen: