From f19aa5ebf36a672aa9d62cf64a0961027bb9726d Mon Sep 17 00:00:00 2001 From: Alain Dumesny Date: Sat, 22 Apr 2023 17:08:40 -0700 Subject: [PATCH] Break: GridStackWidget.subGridOpts rename * `GridStackOptions.subGrid` -> `GridStackOptions.subGridOpts`. * We now have `GridStackWidget.subGridOpts` vs `GridStackNode.subGrid` (subclass) rather than try to merge the two at runtime since very different types... always bugged me to have different runtime types, as it's error prone... --- demo/angular/src/app/app.component.ts | 13 ++++---- demo/angular/src/app/gridstack.component.ts | 2 +- demo/nested.html | 4 +-- demo/nested_advanced.html | 10 +++--- demo/nested_constraint.html | 4 +-- demo/old_nested-jq.html | 4 +-- doc/CHANGES.md | 1 + src/gridstack.ts | 37 +++++++++++---------- src/types.ts | 12 ++++--- 9 files changed, 46 insertions(+), 41 deletions(-) diff --git a/demo/angular/src/app/app.component.ts b/demo/angular/src/app/app.component.ts index 3e62abdc5..75b4ca883 100644 --- a/demo/angular/src/app/app.component.ts +++ b/demo/angular/src/app/app.component.ts @@ -51,8 +51,8 @@ export class AppComponent implements OnInit { private sub2: NgGridStackWidget[] = [ {x:0, y:0}, {x:0, y:1, w:2}]; private subChildren: NgGridStackWidget[] = [ {x:0, y:0, content: 'regular item'}, - {x:1, y:0, w:4, h:4, subGrid: {children: this.sub1, id:'sub1_grid', class: 'sub1', ...this.subOptions}}, - {x:5, y:0, w:3, h:4, subGrid: {children: this.sub2, id:'sub2_grid', class: 'sub2', ...this.subOptions}}, + {x:1, y:0, w:4, h:4, subGridOpts: {children: this.sub1, id:'sub1_grid', class: 'sub1', ...this.subOptions}}, + {x:5, y:0, w:3, h:4, subGridOpts: {children: this.sub2, id:'sub2_grid', class: 'sub2', ...this.subOptions}}, ] public nestedGridOptions: GridStackOptions = { // main grid options cellHeight: 50, @@ -68,7 +68,7 @@ export class AppComponent implements OnInit { constructor() { // give them content and unique id to make sure we track them during changes below... [...this.items, ...this.subChildren, ...this.sub1, ...this.sub2].forEach((w: NgGridStackWidget) => { - if (!w.type && !w.subGrid) w.content = `item ${ids}`; + if (!w.type && !w.subGridOpts) w.content = `item ${ids}`; w.id = String(ids++); }); } @@ -141,9 +141,10 @@ export class AppComponent implements OnInit { let grid = this.gridComp?.grid; if (!grid) return; let node = grid.engine.nodes[0]; - if (node?.subGrid) { - grid = node.subGrid as GridStack; - node = grid?.engine.nodes[0]; + // delete any children first before subGrid itself... + if (node?.subGrid && node.subGrid.engine.nodes.length) { + grid = node.subGrid; + node = grid.engine.nodes[0]; } if (node) grid.removeWidget(node.el!); } diff --git a/demo/angular/src/app/gridstack.component.ts b/demo/angular/src/app/gridstack.component.ts index 3869c4700..8d33a3ee8 100644 --- a/demo/angular/src/app/gridstack.component.ts +++ b/demo/angular/src/app/gridstack.component.ts @@ -216,7 +216,7 @@ export function gsCreateNgComponents(host: GridCompHTMLElement | HTMLElement, w: // IFF we're not a subGrid, define what type of component to create as child, OR you can do it GridstackItemComponent template, but this is more generic const type = (w as NgGridStackWidget).type; - if (!w.subGrid && type && GridstackComponent.selectorToType[type]) { + if (!w.subGridOpts && type && GridstackComponent.selectorToType[type]) { gridItem?.container?.createComponent(GridstackComponent.selectorToType[type]); } diff --git a/demo/nested.html b/demo/nested.html index 2d05e8952..ef9f63d3a 100644 --- a/demo/nested.html +++ b/demo/nested.html @@ -51,8 +51,8 @@

Nested grids demo

id: 'main', children: [ {x:0, y:0, content: 'regular item'}, - {x:1, y:0, w:4, h:4, subGrid: {children: sub1, id:'sub1_grid', class: 'sub1', ...subOptions}}, - {x:5, y:0, w:3, h:4, subGrid: {children: sub2, id:'sub2_grid', class: 'sub2', ...subOptions}}, + {x:1, y:0, w:4, h:4, subGridOpts: {children: sub1, id:'sub1_grid', class: 'sub1', ...subOptions}}, + {x:5, y:0, w:3, h:4, subGridOpts: {children: sub2, id:'sub2_grid', class: 'sub2', ...subOptions}}, ] }; diff --git a/demo/nested_advanced.html b/demo/nested_advanced.html index e34e3150f..4c6a44688 100644 --- a/demo/nested_advanced.html +++ b/demo/nested_advanced.html @@ -45,19 +45,19 @@

Advanced Nested grids demo

let main = [{x:0, y:0}, {x:0, y:1}, {x:1, y:0}] let sub1 = [{x:0, y:0}]; let sub0 = [{x:0, y:0}, {x:1, y:0}]; - // let sub0 = [{x:0, y:0}, {x:1, y:0}, {x:1, y:1, h:2, subGrid: {children: sub1, ...subOptions}}]; + // let sub0 = [{x:0, y:0}, {x:1, y:0}, {x:1, y:1, h:2, subGridOpts: {children: sub1, ...subOptions}}]; let options = { // main grid options cellHeight: 50, margin: 5, minRow: 2, // don't collapse when empty acceptWidgets: true, - subGrid: subOptions, + subGridOpts: subOptions, subGridDynamic: true, // v7 api to create sub-grids on the fly children: [ ...main, - {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: "
nested grid here
"*/}, + {x:2, y:0, w:2, h:3, id: 'sub0', subGridOpts: {children: sub0, ...subOptions}}, + {x:4, y:0, h:2, id: 'sub1', subGridOpts: {children: sub1, ...subOptions}}, + // {x:2, y:0, w:2, h:3, subGridOpts: {children: [...sub1, {x:0, y:1, subGridOpts: subOptions}], ...subOptions}/*,content: "
nested grid here
"*/}, ] }; let count = 0; diff --git a/demo/nested_constraint.html b/demo/nested_constraint.html index 5d6c62604..615ba5e73 100644 --- a/demo/nested_constraint.html +++ b/demo/nested_constraint.html @@ -55,8 +55,8 @@

Constraint Nested grids demo

id: 'main', children: [ {y:0, content: 'regular item'}, - {x:1, w:4, h:4, subGrid: {children: sub1, class: 'sub1', ...subOptions}}, - {x:5, w:4, h:4, subGrid: {children: sub2, class: 'sub2', ...subOptions}}, + {x:1, w:4, h:4, subGridOpts: {children: sub1, class: 'sub1', ...subOptions}}, + {x:5, w:4, h:4, subGridOpts: {children: sub2, class: 'sub2', ...subOptions}}, ] }; diff --git a/demo/old_nested-jq.html b/demo/old_nested-jq.html index dd7449b3e..4f320ab09 100644 --- a/demo/old_nested-jq.html +++ b/demo/old_nested-jq.html @@ -76,8 +76,8 @@

Nested JQuery grids demo

id: 'main', children: [ {x:0, y:0, content: 'regular item'}, - {x:1, w:4, h:4, subGrid: {children: sub1, dragOut: true, class: 'sub1', ...subOptions}}, - {x:5, w:3, h:4, subGrid: {children: sub2, dragOut: false, class: 'sub2', ...subOptions}}, + {x:1, w:4, h:4, subGridOpts: {children: sub1, dragOut: true, class: 'sub1', ...subOptions}}, + {x:5, w:3, h:4, subGridOpts: {children: sub2, dragOut: false, class: 'sub2', ...subOptions}}, ] }; diff --git a/doc/CHANGES.md b/doc/CHANGES.md index f8be404db..14c068ca8 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -91,6 +91,7 @@ Change log * add: `GridStack.saveCB` global callback for each item during save so app can insert any custom data before serializing it. `save()` can now be passed optional callback * move: `GridStack.addRemoveCB` is now global instead of grid option. `load()` can still be passed different optional callback * fix: addGrid() to handle passing an existing initialized grid already +* break: `GridStackOptions.subGrid` -> `GridStackOptions.subGridOpts`. We now have `GridStackWidget.subGridOpts` vs `GridStackNode.subGrid` (subclass) rather than try to merge the two at runtime since very different types... ## 7.3.0 (2023-04-01) * feat [#2229](https://github.com/gridstack/gridstack.js/pull/2229) support nonce for CSP. Thank you [@jedwards1211](https://github.com/jedwards1211) diff --git a/src/gridstack.ts b/src/gridstack.ts index 1f894ed12..aba695461 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -469,8 +469,8 @@ export class GridStack { this._updateContainerHeight(); // see if there is a sub-grid to create - if (node.subGrid) { - this.makeSubGrid(node.el, undefined, undefined, false); //node.subGrid will be used as option in method, no need to pass + if (node.subGridOpts) { + this.makeSubGrid(node.el, node.subGridOpts, undefined, false); // node.subGrid will be used as option in method, no need to pass } // if we're adding an item into 1 column (_prevColumn is set only when going to 1) make sure @@ -498,18 +498,18 @@ export class GridStack { if (!node) { node = this.makeWidget(el).gridstackNode; } - if ((node.subGrid as GridStack)?.el) return node.subGrid as GridStack; // already done + if (node.subGrid?.el) return node.subGrid; // already done // 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; + subGridTemplate = grid.opts?.subGridOpts; grid = grid.parentGridItem?.grid; } //... and set the create options - ops = Utils.cloneDeep({...(subGridTemplate || {}), children: undefined, ...(ops || node.subGrid as GridStackOptions)}); - node.subGrid = ops; + ops = Utils.cloneDeep({...(subGridTemplate || {}), children: undefined, ...(ops || node.subGridOpts)}); + node.subGridOpts = ops; // if column special case it set, remember that flag and set default let autoColumn: boolean; @@ -527,7 +527,7 @@ export class GridStack { this._removeDD(node.el); // remove D&D since it's set on content div newItemOpt = {...node, x:0, y:0}; Utils.removeInternalForSave(newItemOpt); - delete newItemOpt.subGrid; + delete newItemOpt.subGridOpts; if (node.content) { newItemOpt.content = node.content; delete node.content; @@ -625,9 +625,10 @@ export class GridStack { } else { if (!saveContent && !saveCB) { delete n.content; } // check for nested grid - if ((n.subGrid as GridStack)?.el) { - const listOrOpt = (n.subGrid as GridStack).save(saveContent, saveGridOpt, saveCB); - n.subGrid = (saveGridOpt ? listOrOpt : {children: listOrOpt}) as GridStackOptions; + if (n.subGrid?.el) { + const listOrOpt = n.subGrid.save(saveContent, saveGridOpt, saveCB); + n.subGridOpts = (saveGridOpt ? listOrOpt : {children: listOrOpt}) as GridStackOptions; + delete n.subGrid; } } delete n.el; @@ -711,10 +712,10 @@ export class GridStack { let item = (w.id || w.id === 0) ? this.engine.nodes.find(n => n.id === w.id) : undefined; if (item) { this.update(item.el, w); - if (w.subGrid && (w.subGrid as GridStackOptions).children) { // update any sub grid as well + if (w.subGridOpts?.children) { // update any sub grid as well let sub = item.el.querySelector('.grid-stack') as GridHTMLElement; if (sub && sub.gridstack) { - sub.gridstack.load((w.subGrid as GridStackOptions).children); // TODO: support updating grid options ? + sub.gridstack.load(w.subGridOpts.children); // TODO: support updating grid options ? this._insertNotAppend = true; // got reset by above call } } @@ -1138,7 +1139,7 @@ export class GridStack { this._setupAcceptWidget(); this.engine.nodes.forEach(n => { this._prepareDragDropByNode(n); // either delete or init Drag&drop - if (n.subGrid && recurse) (n.subGrid as GridStack).setStatic(val, updateClass, recurse); + if (n.subGrid && recurse) n.subGrid.setStatic(val, updateClass, recurse); }); if (updateClass) { this._setStaticClass(); } return this; @@ -1553,7 +1554,7 @@ export class GridStack { // finally update any nested grids this.engine.nodes.forEach(n => { - if (n.subGrid) {(n.subGrid as GridStack).onParentResize()} + if (n.subGrid) n.subGrid.onParentResize() }); return this; @@ -1757,7 +1758,7 @@ export class GridStack { this.opts.disableDrag = !doEnable; // FIRST before we update children as grid overrides #1658 this.engine.nodes.forEach(n => { this.movable(n.el, doEnable); - if (n.subGrid && recurse) (n.subGrid as GridStack).enableMove(doEnable, recurse); + if (n.subGrid && recurse) n.subGrid.enableMove(doEnable, recurse); }); return this; } @@ -1771,7 +1772,7 @@ export class GridStack { this.opts.disableResize = !doEnable; // FIRST before we update children as grid overrides #1658 this.engine.nodes.forEach(n => { this.resizable(n.el, doEnable); - if (n.subGrid && recurse) (n.subGrid as GridStack).enableResize(doEnable, recurse); + if (n.subGrid && recurse) n.subGrid.enableResize(doEnable, recurse); }); return this; } @@ -1987,7 +1988,7 @@ export class GridStack { if (!wasAdded) return false; el.gridstackNode = node; node.el = el; - let subGrid = (node.subGrid as GridStack)?.el?.gridstack; // set when actual sub-grid present + let subGrid = node.subGrid?.el?.gridstack; // set when actual sub-grid present // @ts-ignore Utils.copyPos(node, this._readAttr(this.placeholder)); // placeholder values as moving VERY fast can throw things off #1578 Utils.removePositioningStyles(el);// @ts-ignore @@ -2263,7 +2264,7 @@ export class GridStack { node._lastUiPosition = ui.position; this.engine.cacheRects(cellWidth, cellHeight, mTop, mRight, mBottom, mLeft); delete node._skipDown; - if (resizing && node.subGrid) { (node.subGrid as GridStack).onParentResize(); }// @ts-ignore + if (resizing && node.subGrid) node.subGrid.onParentResize(); this._extraDragRow = 0;// @ts-ignore this._updateContainerHeight(); diff --git a/src/types.ts b/src/types.ts index fbea2ea52..1f1d063c1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -252,8 +252,8 @@ export interface GridStackOptions { /** if `true` will add style element to `` otherwise will add it to element's parent node (default `false`). */ styleInHead?: boolean; - /** list of differences in options for automatically created sub-grids under us */ - subGrid?: GridStackOptions; + /** list of differences in options for automatically created sub-grids under us (inside our grid-items) */ + subGridOpts?: GridStackOptions; /** enable/disable the creation of sub-grids on the fly by dragging items completely * over others (nest) vs partially (push). Forces `DDDragOpt.pause=true` to accomplish that. */ @@ -318,8 +318,8 @@ export interface GridStackWidget extends GridStackPosition { id?: numberOrString; /** html to append inside as content */ content?: string; - /** optional nested grid options and list of children, which then turns into actual instance at runtime */ - subGrid?: GridStackOptions | GridStack; + /** optional nested grid options and list of children, which then turns into actual instance at runtime to get options from */ + subGridOpts?: GridStackOptions; } /** Drag&Drop resize options */ @@ -390,8 +390,10 @@ export interface DDUIData { export interface GridStackNode extends GridStackWidget { /** pointer back to HTML element */ el?: GridItemHTMLElement; - /** pointer back to Grid instance */ + /** pointer back to parent Grid instance */ grid?: GridStack; + /** actual sub-grid instance */ + subGrid?: GridStack; /** @internal internal id used to match when cloning engines or saving column layouts */ _id?: number; /** @internal */