Skip to content

nested grid save() incorrectly re-list children #2173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ If unsure if lib bug, use slack channel instead: https://join.slack.com/t/gridst
You **MUST** provide a working demo - keep it simple and avoid frameworks as that could have issues - you can use
https://jsfiddle.net/adumesny/jqhkry7g

## Actual behavior
Tell us what happens instead of what's expected. If hard to describe, attach a video as well.
## Expected behavior
Tell us what should happen. If hard to describe, attach a video as well.
32 changes: 19 additions & 13 deletions demo/nested_advanced.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@ <h1>Advanced Nested grids demo</h1>
<a class="btn btn-primary" onClick="addNewWidget(0)" href="#">Add W Grid0</a>
<a class="btn btn-primary" onClick="addNewWidget(1)" href="#">Add W Grid1</a>
<a class="btn btn-primary" onClick="addNewWidget(2)" href="#">Add W Grid2</a>
<span>entire save/re-create:</span>
<a class="btn btn-primary" onClick="save()" href="#">Save</a>
<span>entire option+layout:</span>
<a class="btn btn-primary" onClick="save()" href="#">Save Full</a>
<a class="btn btn-primary" onClick="destroy()" href="#">Destroy</a>
<a class="btn btn-primary" onClick="load()" href="#">Load</a>
<span>partial save/load:</span>
<a class="btn btn-primary" onClick="save(true, false)" href="#">Save list</a>
<a class="btn btn-primary" onClick="save(false, false)" href="#">Save no content</a>
<a class="btn btn-primary" onClick="load()" href="#">Re-create</a>
<span>layout list:</span>
<a class="btn btn-primary" onClick="save(true, false)" href="#">Save layout</a>
<a class="btn btn-primary" onClick="save(false, false)" href="#">Save layout no content</a>
<a class="btn btn-primary" onClick="destroy(false)" href="#">Clear</a>
<a class="btn btn-primary" onClick="load(false)" href="#">Load</a>
<br><br>
<!-- grid will be added here -->
</div>

<p>Output</p>
<textarea id="saved" style="width:100%; height:200px;"></textarea>
<script type="text/javascript">
let subOptions = {
cellHeight: 50, // should be 50 - top/bottom
Expand All @@ -54,15 +55,17 @@ <h1>Advanced Nested grids demo</h1>
subGridDynamic: true, // v7 api to create sub-grids on the fly
children: [
...main,
{x:2, y:0, w:2, h:3, subGrid: {children: sub0, ...subOptions}},
{x:4, y:0, h:2, subGrid: {children: sub1, ...subOptions}},
{x:2, y:0, w:2, h:3, id: 'sub0', subGrid: {children: sub0, ...subOptions}},
{x:4, y:0, h:2, id: 'sub1', subGrid: {children: sub1, ...subOptions}},
// {x:2, y:0, w:2, h:3, subGrid: {children: [...sub1, {x:0, y:1, subGrid: subOptions}], ...subOptions}/*,content: "<div>nested grid here</div>"*/},
]
};
let count = 0;
[...main, ...sub0, ...sub1].forEach(d => {if (!d.subGrid) d.content = String(count++)});
// create unique ids+content so we can incrementally load() and not re-create anything (updates)
[...main, ...sub0, ...sub1].forEach(d => d.id = d.content = String(count++));

// create and load it all from JSON above
document.querySelector('#saved').value = JSON.stringify(options);
let grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);

function addMainWidget() {
Expand All @@ -84,11 +87,12 @@ <h1>Advanced Nested grids demo</h1>
};

function save(content = true, full = true) {
options = grid.save(content, full);
options = grid?.save(content, full);
console.log(options);
// console.log(JSON.stringify(options));
document.querySelector('#saved').value = JSON.stringify(options);
}
function destroy(full = true) {
if (!grid) return;
if (full) {
grid.destroy();
grid = undefined;
Expand All @@ -97,13 +101,15 @@ <h1>Advanced Nested grids demo</h1>
}
}
function load(full = true) {
if (full) {
// destroy(full); // in case user didn't call
if (full || !grid) {
grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
} else {
grid.load(options);
}
}

// save(true, false); load(false); // TESTing
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions doc/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Change log
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*

- [7.2.1-dev (TBD)](#721-dev-tbd)
- [7.2.1 (2023-01-14)](#721-2023-01-14)
- [7.2.0 (2023-01-07)](#720-2023-01-07)
- [7.1.2 (2022-12-29)](#712-2022-12-29)
Expand Down Expand Up @@ -78,6 +79,10 @@ Change log
- [v0.1.0 (2014-11-18)](#v010-2014-11-18)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## 7.2.1-dev (TBD)
* fix [#2171](https://github.com/gridstack/gridstack.js/issues/2171) `save()` nested grid has extra nested children & options

## 7.2.1 (2023-01-14)
* fix [#2162](https://github.com/gridstack/gridstack.js/pull/2162) removing item from a grid (into another) will now call `change` if anything was also modified during the remove
* fix [#2110](https://github.com/gridstack/gridstack.js/issues/2110) custom `GridStackOptions.itemClass` now works when dragging from outside
Expand Down
20 changes: 14 additions & 6 deletions src/gridstack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ export class GridStack {
this._prepareElement(el, true, options);
this._updateContainerHeight();

// see if there is a sub-grid to create too
// see if there is a sub-grid to create
if (node.subGrid) {
this.makeSubGrid(node.el, undefined, undefined, false);
}
Expand All @@ -472,7 +472,7 @@ export class GridStack {

/**
* Convert an existing gridItem element into a sub-grid with the given (optional) options, else inherit them
* from the parent subGrid options.
* from the parent's subGrid options.
* @param el gridItem element to convert
* @param ops (optional) sub-grid options, else default to node, then parent settings, else defaults
* @param nodeToAdd (optional) node to add to the newly created sub grid (used when dragging over existing regular item)
Expand All @@ -485,8 +485,15 @@ export class GridStack {
}
if ((node.subGrid as GridStack)?.el) return node.subGrid as GridStack; // already done

ops = Utils.cloneDeep(ops || node.subGrid as GridStackOptions || {...this.opts.subGrid, children: undefined});
ops.subGrid = Utils.cloneDeep(ops); // carry nesting settings to next one down
// find the template subGrid stored on a parent as fallback...
let subGridTemplate: GridStackOptions; // eslint-disable-next-line @typescript-eslint/no-this-alias
let grid: GridStack = this;
while (grid && !subGridTemplate) {
subGridTemplate = grid.opts?.subGrid;
grid = grid.parentGridItem?.grid;
}
//... and set the create options
ops = Utils.cloneDeep({...(subGridTemplate || {}), children: undefined, ...(ops || node.subGrid as GridStackOptions)});
node.subGrid = ops;

// if column special case it set, remember that flag and set default
Expand Down Expand Up @@ -599,8 +606,9 @@ export class GridStack {
} else {
if (!saveContent) { delete n.content; }
// check for nested grid
if (n.subGrid) {
n.subGrid = (n.subGrid as GridStack).save(saveContent, true) as GridStackOptions;
if ((n.subGrid as GridStack)?.el) {
const listOrOpt = (n.subGrid as GridStack).save(saveContent, saveGridOpt);
n.subGrid = (saveGridOpt ? listOrOpt : {children: listOrOpt}) as GridStackOptions;
}
}
delete n.el;
Expand Down