diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 7f22b0b14..54e2123fa 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -103,6 +103,7 @@ Change log ## 9.2.1-dev (TBD) * fix - sub-grid styles now look for immediate correct parent, not any depth above. * fix [#2469](https://github.com/gridstack/gridstack.js/issues/2469) "Invalid height" error CSS minHeight +* fix [#2394](https://github.com/gridstack/gridstack.js/issues/2394) nested grid size issue when sub-items moved up/down ## 9.2.1 (2023-09-20) * fix _updateContainerHeight() to use height rather than min-height again (apart for nested grids which need it) and partial getComputedStyle CSS minHeight support diff --git a/spec/e2e/html/2394_save_sub_item_moved.html b/spec/e2e/html/2394_save_sub_item_moved.html new file mode 100644 index 000000000..901b36dff --- /dev/null +++ b/spec/e2e/html/2394_save_sub_item_moved.html @@ -0,0 +1,60 @@ + + + + + + + #2394 Save sub item moved + + + + + + + +

#2394 Save sub item moved

+ + + +

+
+ + + + diff --git a/src/gridstack-engine.ts b/src/gridstack-engine.ts index db35bc5c7..70cd55287 100644 --- a/src/gridstack-engine.ts +++ b/src/gridstack-engine.ts @@ -392,9 +392,9 @@ export class GridStackEngine { const saveOrig = (node.x || 0) + (node.w || 1) > this.column; if (saveOrig && this.column < 12 && !this._inColumnResize && node._id && this.findCacheLayout(node, 12) === -1) { let copy = {...node}; // need _id + positions - if (copy.autoPosition) { delete copy.x; delete copy.y; } + if (copy.autoPosition || copy.x === undefined) { delete copy.x; delete copy.y; } else copy.x = Math.min(11, copy.x); - copy.w = Math.min(12, copy.w); + copy.w = Math.min(12, copy.w || 1); this.cacheOneLayout(copy, 12); } @@ -744,9 +744,8 @@ export class GridStackEngine { this.sortNodes(); this.nodes.forEach(n => { let wl = layout?.find(l => l._id === n._id); - let w: GridStackNode = {...n}; - // use layout info instead if set - if (wl) { w.x = wl.x; w.y = wl.y; w.w = wl.w; } + // use layout info fields instead if set + let w: GridStackNode = {...n, ...(wl || {})}; Utils.removeInternalForSave(w, !saveElement); if (saveCB) saveCB(n, w); list.push(w); @@ -943,7 +942,7 @@ export class GridStackEngine { public cacheOneLayout(n: GridStackNode, column: number): GridStackEngine { n._id = n._id ?? GridStackEngine._idSeq++; let l: GridStackNode = {x: n.x, y: n.y, w: n.w, _id: n._id} - if (n.autoPosition) { delete l.x; delete l.y; l.autoPosition = true; } + if (n.autoPosition || n.x === undefined) { delete l.x; delete l.y; if (n.autoPosition) l.autoPosition = true; } this._layouts = this._layouts || []; this._layouts[column] = this._layouts[column] || []; let index = this.findCacheLayout(n, column); diff --git a/src/gridstack.ts b/src/gridstack.ts index e9d265df8..01d2ade59 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -2042,12 +2042,14 @@ export class GridStack { // console.log('dropover cloning node'); // TEST if (!el._gridstackNodeOrig) el._gridstackNodeOrig = node; // shouldn't have multiple nested! el.gridstackNode = node = {...node, w, h, grid: this}; + delete node.x; + delete node.y; this.engine.cleanupNode(node) .nodeBoundFix(node); // restore some internal fields we need after clearing them all node._initDD = - node._isExternal = // DOM needs to be re-parented on a drop - node._temporaryRemoved = true; // so it can be inserted onDrag below + node._isExternal = // DOM needs to be re-parented on a drop + node._temporaryRemoved = true; // so it can be inserted onDrag below } else { node.w = w; node.h = h; node._temporaryRemoved = true; // so we can insert it @@ -2096,6 +2098,7 @@ export class GridStack { delete el._gridstackNodeOrig; if (wasAdded && origNode?.grid && origNode.grid !== this) { let oGrid = origNode.grid; + oGrid.engine.removeNodeFromLayoutCache(origNode); oGrid.engine.removedNodes.push(origNode); oGrid._triggerRemoveEvent()._triggerChangeEvent(); // if it's an empty sub-grid that got auto-created, nuke it @@ -2141,7 +2144,6 @@ export class GridStack { this._updateContainerHeight(); this.engine.addedNodes.push(node);// @ts-ignore this._triggerAddEvent();// @ts-ignore - this.engine.removeNodeFromLayoutCache(node); this._triggerChangeEvent(); this.engine.endUpdate();