Hi,
I tried setting up Grid state for localStorage but the expand/collapse state of each record are not saved. What is the best way to save the state of expand/collapse of each row?
StateProvider.setup('local');
Thanks
Hey rodel.ocfemia,
You can check this guide to understand better how to save information related to the Grid https://bryntum.com/products/grid/docs/api/Core/mixin/State#implementing-stateful-components
And you could listen to expand/collapse events and trigger the saveState function https://bryntum.com/products/grid/docs/api/Grid/feature/RowExpander#event-beforeExpand
https://bryntum.com/products/grid/docs/api/Grid/feature/RowExpander#event-beforeCollapse
https://bryntum.com/products/grid/docs/api/Core/mixin/State#function-saveState
Best regards,
Márcio
Hi marcio,
I have the following code. The StateProvider.saveState() does not return any error. But how to load the saved stated on load of grid? I tried invoking StateProvider.loadState('mainGrid',true) inside renderRows event but it throws error.
ProjectGrid = () => {
const gridConfig = {
stateId: 'mainGrid',
store: new AjaxStore({
readUrl: 'http://localhost/project/projectgrid/data',
autoLoad: true,
}),
treeFeature: true,
columns: [
{
type: 'tree',
text: '',
field: 'name',
width: 200,
readonly: true,
},
],
listeners: {
beforeCollapse: (props: any) => {
StateProvider.saveState();
},
beforeExpand: (props: any) => {
StateProvider.saveState();
},
renderRows: (props: any) => {
StateProvider.loadState('mainGrid',true); //this throws error
}
};
const grid = useRef<any>(null);
return <BryntumGrid ref={grid} {...gridConfig} />;
};
}
Hey,
Did you initiate the StateProvider correctly? Check this demo to see how it's done https://bryntum.com/products/grid/examples/state/
It uses the setup function you shared in the first post.
if ((new URL(window.location)).searchParams.get('state') === 'remote') { // if ('?state=remote' in URL)
// For server-side state, initialize the page widgets after the state is loaded from the server.
(new BackendState(StateProvider.setup('memory'))).init().then(launch);
}
else {
// To use localStorage instead of a backend for state, the launch process is simply this:
StateProvider.setup('local');
launch();
}
Best regards,
Márcio
Hi Marcio,
Yes I initiated this code StateProvider.setup('local').
Please see attached runnable code.
I've added also the following code to save the expand/collapse state.
listeners: {
collapseNode: (props: any) => {
const { source } = props;
source.saveState();
console.log('collapseNode')
},
expandNode: (props: any) => {
const { source } = props;
source.saveState();
console.log('expandNode')
},
},
Hi,
I assume there is some misunderstanding here.
expand
/collapse
state of records is not stored in state provider. It is a data field of a record and should be stored in db on server side.
See https://bryntum.com/products/grid/docs/api/Grid/data/GridRowModel#field-expanded
So, you need to make this field persist: true
and save it as any other data field change.
https://bryntum.com/products/grid/docs/api/Core/data/field/DataField#config-persist
https://bryntum.com/products/grid/docs/api/Core/data/AjaxStore#config-modelClass
class MyModel extends GridRowModel {
static get fields() {
return [
{ name : 'expanded', persist : true }
]
}
[...]
const store = new AjaxStore({
modelClass : MyModel
});
});
All the best,
Alex
Hi Alex,
Right now, we can only save user preference including expand/collapse in the user's browser. So I created a custom StateHelper class that saves the expand/collapse to localStorage. See attached rerunnable code.
The saving part works fine as follows.
listeners: {
collapseNode: (props: any) => {
const { record, source } = props;
const data = {
id: record.id,
expanded: false,
};
StateHelper.saveExpandCollapse(data);
},
expandNode: (props: any) => {
const { record, source } = props;
const data = {
id: record.id,
expanded: true,
};
StateHelper.saveExpandCollapse(data);
},
}
On rendering, I'm invoking it on renderRow. It also works fine. It renders whatever I saved on localStorage.
The issue is that I am unable to trigger the collapse anymore. Please advise how can I fix the issue.
renderRow: (props: any) => {
const { record, source } = props;
const expandCollapseState = StateHelper.getExpandCollapse();
if (expandCollapseState) {
const row = expandCollapseState.items.filter((x: any) => x.id === record.id);
if (row.length) {
source.grid.toggleCollapse(record, !row[0].expanded);
}
}
},
Hi,
The issue is that I am unable to trigger the collapse anymore. Please advise how can I fix the issue.
Could you please explain what did you mean here? Unable to collapse node programmatically? Unable to catch node collapse action?
I would try in your case to manipulate with data and set expanded
field value before you load (apply) data to the store instead of manipulate already loaded and rendered data.
All the best,
Alex
Hi Alex,
To recreate the issue:
All the saving and loading of state are placed inside the following code.
Note: If I comment the code inside renderRow, clicking expand or collapse icon works. But on load, the saved state is not reflected. The code in renderRow is the one that applies the expand/collapse on load.
listeners: {
collapseNode: (props: any) => {
const { record, source } = props;
const data = {
id: record.id,
expanded: false,
};
StateHelper.saveExpandCollapse(data);
},
expandNode: (props: any) => {
const { record, source } = props;
const data = {
id: record.id,
expanded: true,
};
StateHelper.saveExpandCollapse(data);
},
renderRow: (props: any) => {
const { record, source } = props;
const expandCollapseState = StateHelper.getExpandCollapse();
if (expandCollapseState) {
const row = expandCollapseState.items.filter((x: any) => x.id === record.id);
if (row.length) {
source.grid.toggleCollapse(record, !row[0].expanded);
}
}
},
},
Hi, the solution is not valid. You are changing node state while rendering that causes collisions. It won't be working this way.
There are 2 options:
data
before load to store. state
from localStore, change expanded
field value for all required records and load/set data to store after that. You can add your code into useGridConfig
method above return
object.In 2 words, expanded/collapse state of nodes - is data layer level. So I suggest you to work with it on data level. I am not sure if you used static data in your real app, but in any case there is a way to apply state on data before rendering.
All the best,
Alex