Skip to content

Commit c1affaf

Browse files
committed
nested grid save() incorrectly re-list children
* fix #2171 * we no longer store ops.subGrid for each nested grid. instead we parse the top grid that has this info and re-use it during create * save() now handles saving only layout of subGrid more efficiently (don't list options) * updated demo to showcase the issues
1 parent d3af197 commit c1affaf

File tree

4 files changed

+40
-21
lines changed

4 files changed

+40
-21
lines changed

ISSUE_TEMPLATE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ If unsure if lib bug, use slack channel instead: https://join.slack.com/t/gridst
1010
You **MUST** provide a working demo - keep it simple and avoid frameworks as that could have issues - you can use
1111
https://jsfiddle.net/adumesny/jqhkry7g
1212

13-
## Actual behavior
14-
Tell us what happens instead of what's expected. If hard to describe, attach a video as well.
13+
## Expected behavior
14+
Tell us what should happen. If hard to describe, attach a video as well.

demo/nested_advanced.html

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,20 @@ <h1>Advanced Nested grids demo</h1>
2020
<a class="btn btn-primary" onClick="addNewWidget(0)" href="#">Add W Grid0</a>
2121
<a class="btn btn-primary" onClick="addNewWidget(1)" href="#">Add W Grid1</a>
2222
<a class="btn btn-primary" onClick="addNewWidget(2)" href="#">Add W Grid2</a>
23-
<span>entire save/re-create:</span>
24-
<a class="btn btn-primary" onClick="save()" href="#">Save</a>
23+
<span>entire option+layout:</span>
24+
<a class="btn btn-primary" onClick="save()" href="#">Save Full</a>
2525
<a class="btn btn-primary" onClick="destroy()" href="#">Destroy</a>
26-
<a class="btn btn-primary" onClick="load()" href="#">Load</a>
27-
<span>partial save/load:</span>
28-
<a class="btn btn-primary" onClick="save(true, false)" href="#">Save list</a>
29-
<a class="btn btn-primary" onClick="save(false, false)" href="#">Save no content</a>
26+
<a class="btn btn-primary" onClick="load()" href="#">Re-create</a>
27+
<span>layout list:</span>
28+
<a class="btn btn-primary" onClick="save(true, false)" href="#">Save layout</a>
29+
<a class="btn btn-primary" onClick="save(false, false)" href="#">Save layout no content</a>
3030
<a class="btn btn-primary" onClick="destroy(false)" href="#">Clear</a>
3131
<a class="btn btn-primary" onClick="load(false)" href="#">Load</a>
3232
<br><br>
3333
<!-- grid will be added here -->
3434
</div>
35-
35+
<p>Output</p>
36+
<textarea id="saved" style="width:100%; height:200px;"></textarea>
3637
<script type="text/javascript">
3738
let subOptions = {
3839
cellHeight: 50, // should be 50 - top/bottom
@@ -54,15 +55,17 @@ <h1>Advanced Nested grids demo</h1>
5455
subGridDynamic: true, // v7 api to create sub-grids on the fly
5556
children: [
5657
...main,
57-
{x:2, y:0, w:2, h:3, subGrid: {children: sub0, ...subOptions}},
58-
{x:4, y:0, h:2, subGrid: {children: sub1, ...subOptions}},
58+
{x:2, y:0, w:2, h:3, id: 'sub0', subGrid: {children: sub0, ...subOptions}},
59+
{x:4, y:0, h:2, id: 'sub1', subGrid: {children: sub1, ...subOptions}},
5960
// {x:2, y:0, w:2, h:3, subGrid: {children: [...sub1, {x:0, y:1, subGrid: subOptions}], ...subOptions}/*,content: "<div>nested grid here</div>"*/},
6061
]
6162
};
6263
let count = 0;
63-
[...main, ...sub0, ...sub1].forEach(d => {if (!d.subGrid) d.content = String(count++)});
64+
// create unique ids+content so we can incrementally load() and not re-create anything (updates)
65+
[...main, ...sub0, ...sub1].forEach(d => d.id = d.content = String(count++));
6466

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

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

8689
function save(content = true, full = true) {
87-
options = grid.save(content, full);
90+
options = grid?.save(content, full);
8891
console.log(options);
89-
// console.log(JSON.stringify(options));
92+
document.querySelector('#saved').value = JSON.stringify(options);
9093
}
9194
function destroy(full = true) {
95+
if (!grid) return;
9296
if (full) {
9397
grid.destroy();
9498
grid = undefined;
@@ -97,13 +101,15 @@ <h1>Advanced Nested grids demo</h1>
97101
}
98102
}
99103
function load(full = true) {
100-
if (full) {
104+
// destroy(full); // in case user didn't call
105+
if (full || !grid) {
101106
grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
102107
} else {
103108
grid.load(options);
104109
}
105110
}
106111

112+
// save(true, false); load(false); // TESTing
107113
</script>
108114
</body>
109115
</html>

doc/CHANGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Change log
55
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
66
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
77

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

8081
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
82+
83+
## 7.2.1-dev (TBD)
84+
* fix [#2171](https://github.com/gridstack/gridstack.js/issues/2171) `save()` nested grid has extra nested children & options
85+
8186
## 7.2.1 (2023-01-14)
8287
* 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
8388
* fix [#2110](https://github.com/gridstack/gridstack.js/issues/2110) custom `GridStackOptions.itemClass` now works when dragging from outside

src/gridstack.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ export class GridStack {
453453
this._prepareElement(el, true, options);
454454
this._updateContainerHeight();
455455

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

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

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

492499
// if column special case it set, remember that flag and set default
@@ -599,8 +606,9 @@ export class GridStack {
599606
} else {
600607
if (!saveContent) { delete n.content; }
601608
// check for nested grid
602-
if (n.subGrid) {
603-
n.subGrid = (n.subGrid as GridStack).save(saveContent, true) as GridStackOptions;
609+
if ((n.subGrid as GridStack)?.el) {
610+
const listOrOpt = (n.subGrid as GridStack).save(saveContent, saveGridOpt);
611+
n.subGrid = (saveGridOpt ? listOrOpt : {children: listOrOpt}) as GridStackOptions;
604612
}
605613
}
606614
delete n.el;

0 commit comments

Comments
 (0)