From 89b8484715cbc8924948d87ad31c4c6473848231 Mon Sep 17 00:00:00 2001 From: Alain Dumesny Date: Wed, 28 Dec 2022 15:22:10 -0800 Subject: [PATCH 1/2] better GridStackEventHandlerCallback types * GridStackEventHandlerCallback is not a list of specific callbacks so user can have better method signatures. --- demo/events.js | 10 +++++----- doc/CHANGES.md | 1 + src/gridstack.ts | 7 ++++--- src/types.ts | 7 ++++++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/demo/events.js b/demo/events.js index 6d9d75640..df12780b1 100644 --- a/demo/events.js +++ b/demo/events.js @@ -38,12 +38,12 @@ function addEvents(grid, id) { console.log(g + 'dragstop ' + el.textContent + ' pos: (' + node.x + ',' + node.y + ') = (' + x + ',' + y + ')'); }); - grid.on('dropped', function(event, previousWidget, newWidget) { - if (previousWidget) { - console.log(g + 'dropped - Removed widget from grid:', previousWidget); + grid.on('dropped', function(event, previousNode, newNode) { + if (previousNode) { + console.log(g + 'dropped - Removed widget from grid:', previousNode); } - if (newWidget) { - console.log(g + 'dropped - Added widget in grid:', newWidget); + if (newNode) { + console.log(g + 'dropped - Added widget in grid:', newNode); } }); diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 21292f289..83748b5d3 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -80,6 +80,7 @@ Change log ## 7.1.1-dev (TBD) * fix [#939](https://github.com/gridstack/gridstack.js/issues/2039) 'prototype' undefined error for dd-gridstack.js * add [#939](https://github.com/gridstack/gridstack.js/issues/2105) disable/enable are methods now recursive by default +* add better GridStackEventHandlerCallback spelled out types ## 7.1.1 (2022-11-13) * fix [#939](https://github.com/gridstack/gridstack.js/issues/939) editable elements focus (regression in v6). Thank you [@Gezdy](https://github.com/Gezdy) diff --git a/src/gridstack.ts b/src/gridstack.ts index d65b1fb73..55f56160e 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -8,7 +8,8 @@ import { GridStackEngine } from './gridstack-engine'; import { Utils, HeightData, obsolete } from './utils'; import { gridDefaults, ColumnOptions, GridItemHTMLElement, GridStackElement, GridStackEventHandlerCallback, - GridStackNode, GridStackWidget, numberOrString, DDUIData, DDDragInOpt, GridStackPosition, GridStackOptions, dragInDefaultOptions } from './types'; + GridStackNode, GridStackWidget, numberOrString, DDUIData, DDDragInOpt, GridStackPosition, GridStackOptions, + dragInDefaultOptions, GridStackEventHandler, GridStackNodesHandler } from './types'; /* * and include D&D by default @@ -984,9 +985,9 @@ export class GridStack { // native CustomEvent handlers - cash the generic handlers so we can easily remove let noData = (name === 'enable' || name === 'disable'); if (noData) { - this._gsEventHandler[name] = (event: Event) => callback(event); + this._gsEventHandler[name] = (event: Event) => (callback as GridStackEventHandler)(event); } else { - this._gsEventHandler[name] = (event: CustomEvent) => callback(event, event.detail); + this._gsEventHandler[name] = (event: CustomEvent) => (callback as GridStackNodesHandler)(event, event.detail); } this.el.addEventListener(name, this._gsEventHandler[name]); } else if (name === 'drag' || name === 'dragstart' || name === 'dragstop' || name === 'resizestart' || name === 'resize' || name === 'resizestop' || name === 'dropped') { diff --git a/src/types.ts b/src/types.ts index baff9fa63..ad1518026 100644 --- a/src/types.ts +++ b/src/types.ts @@ -66,7 +66,12 @@ export interface GridItemHTMLElement extends HTMLElement { export type GridStackElement = string | HTMLElement | GridItemHTMLElement; -export type GridStackEventHandlerCallback = (event: Event, arg2?: GridItemHTMLElement | GridStackNode | GridStackNode[], newNode?: GridStackNode) => void; +/** specific and general event handlers for the .on() method */ +export type GridStackEventHandler = (event: Event) => void; +export type GridStackElementHandler = (event: Event, el: GridItemHTMLElement) => void; +export type GridStackNodesHandler = (event: Event, node: GridStackNode[]) => void; +export type GridStackDroppedHandler = (event: Event, previousNode: GridStackNode, newNode: GridStackNode) => void; +export type GridStackEventHandlerCallback = GridStackEventHandler | GridStackElementHandler | GridStackNodesHandler | GridStackDroppedHandler; /** * Defines the options for a Grid From be886c8aca6be9e1671f75aeadb02bc16eee675f Mon Sep 17 00:00:00 2001 From: Alain Dumesny Date: Wed, 28 Dec 2022 15:29:46 -0800 Subject: [PATCH 2/2] Angular component examples * better version of #1824 * moved classes to correct place, simplified htm + css to be in .ts template (only 2 files to copy now) * fixed the incorrect event handlers to pass the right set of params for each, cleanup * grid-item simpler elements (matches Nodes fields) MORE TODO.... --- demo/angular/gridstack-item.component.html | 3 - demo/angular/gridstack-item.component.scss | 3 - demo/angular/gridstack-item.component.ts | 34 --- demo/angular/gridstack.component.html | 0 demo/angular/gridstack.component.scss | 33 --- demo/angular/gridstack.component.ts | 279 ------------------ demo/angular/gridstack.module.ts | 20 -- demo/angular/src/app/app.component.html | 8 + demo/angular/src/app/app.component.ts | 15 + demo/angular/src/app/app.module.ts | 4 + .../src/app/gridstack-item.component.ts | 40 +++ demo/angular/src/app/gridstack.component.ts | 193 ++++++++++++ 12 files changed, 260 insertions(+), 372 deletions(-) delete mode 100644 demo/angular/gridstack-item.component.html delete mode 100644 demo/angular/gridstack-item.component.scss delete mode 100644 demo/angular/gridstack-item.component.ts delete mode 100644 demo/angular/gridstack.component.html delete mode 100644 demo/angular/gridstack.component.scss delete mode 100644 demo/angular/gridstack.component.ts delete mode 100644 demo/angular/gridstack.module.ts create mode 100644 demo/angular/src/app/gridstack-item.component.ts create mode 100644 demo/angular/src/app/gridstack.component.ts diff --git a/demo/angular/gridstack-item.component.html b/demo/angular/gridstack-item.component.html deleted file mode 100644 index 01ccdc0bf..000000000 --- a/demo/angular/gridstack-item.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/demo/angular/gridstack-item.component.scss b/demo/angular/gridstack-item.component.scss deleted file mode 100644 index 5d4e87f30..000000000 --- a/demo/angular/gridstack-item.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -:host { - display: block; -} diff --git a/demo/angular/gridstack-item.component.ts b/demo/angular/gridstack-item.component.ts deleted file mode 100644 index 9c1d17191..000000000 --- a/demo/angular/gridstack-item.component.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {ChangeDetectionStrategy, Component, ElementRef, Input, NgZone, OnInit, Renderer2} from '@angular/core'; - -@Component({ - selector: 'ef-gridstack-item', - templateUrl: './gridstack-item.component.html', - styleUrls: ['./gridstack-item.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class GridstackItemComponent implements OnInit { - - @Input() public x: number; - @Input() public y: number; - @Input() public width: number; - @Input() public height: number; - @Input() public minW: number; - @Input() public minH: number; - @Input() public identifier: string; - - constructor( - private readonly ngZone: NgZone, - private readonly _elementRef: ElementRef, - private readonly renderer2: Renderer2, - ) { - } - - get elementRef(): ElementRef { - return this._elementRef; - } - - public ngOnInit(): void { - this.renderer2.addClass(this._elementRef.nativeElement, 'grid-stack-item'); - } - -} diff --git a/demo/angular/gridstack.component.html b/demo/angular/gridstack.component.html deleted file mode 100644 index e69de29bb..000000000 diff --git a/demo/angular/gridstack.component.scss b/demo/angular/gridstack.component.scss deleted file mode 100644 index 249bac810..000000000 --- a/demo/angular/gridstack.component.scss +++ /dev/null @@ -1,33 +0,0 @@ -@use "sass:math"; - -$gridstack-max-columns: 24; - -:host { - display: block; -} - -::ng-deep { - @mixin gen-grid-stack-item-width($gridstack-columns) { - .grid-stack-#{$gridstack-columns} { - .grid-stack-item { - @for $i from 1 through $gridstack-columns { - &[gs-w='#{$i}'] { - width: math.div(100% , $gridstack-columns) * $i; - } - &[gs-x='#{$i}'] { - left: math.div(100% , $gridstack-columns) * $i; - } - &[gs-min-w='#{$i}'] { - min-width: math.div(100% , $gridstack-columns) * $i; - } - &[gs-max-w='#{$i}'] { - max-width: math.div(100% ,$gridstack-columns) * $i; - } - } - } - } - } - @for $i from 1 through $gridstack-max-columns { - @include gen-grid-stack-item-width($i); - } -} diff --git a/demo/angular/gridstack.component.ts b/demo/angular/gridstack.component.ts deleted file mode 100644 index 2f69f0cc7..000000000 --- a/demo/angular/gridstack.component.ts +++ /dev/null @@ -1,279 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - ContentChildren, - ElementRef, - EventEmitter, - Input, - NgZone, - OnDestroy, - OnInit, - Output, - QueryList, - Renderer2, -} from '@angular/core'; -import {GridstackItemComponent} from './gridstack-item.component'; -import {merge, Subject} from 'rxjs'; -import {GridStack, GridStackEvent, GridStackOptions} from 'gridstack'; -import 'gridstack/dist/h5/gridstack-dd-native'; -import {map, takeUntil} from 'rxjs/operators'; - -@Component({ - selector: 'ef-gridstack', - templateUrl: './gridstack.component.html', - styleUrls: ['./gridstack.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class GridstackComponent implements OnInit, OnDestroy { - - @ContentChildren(GridstackItemComponent) public gridstackItems: QueryList; - - @Input() public options: GridStackOptions; - - @Output() public gridstackAdded = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackChange = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackDisable = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackDrag = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackDragStart = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackDragStop = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackDropped = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackEnable = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackRemoved = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackResize = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackResizeStart = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - @Output() public gridstackResizeStop = new EventEmitter<{ - event: GridStackEvent; - grid: GridStack; - }>(); - - private readonly update$ = new Subject(); - private readonly destroy$ = new Subject(); - private _grid: GridStack; - - constructor( - private readonly ngZone: NgZone, - private readonly elementRef: ElementRef, - private readonly renderer2: Renderer2, - ) { - } - - get grid(): GridStack { - return this._grid; - } - - public ngOnInit(): void { - this.renderer2.addClass(this.elementRef.nativeElement, 'grid-stack'); - } - - public ngAfterContentInit(): void { - this.ngZone.runOutsideAngular(() => { - this._grid = GridStack.init(this.options, this.elementRef.nativeElement); - this.hookEvents(this._grid); - merge( - this.update$, - this.gridstackItems.changes, - ).pipe( - map(() => this.gridstackItems.toArray()), - takeUntil(this.destroy$), - ).subscribe(items => { - const gridItems = this._grid.getGridItems(); - let elementsToRemove = [...gridItems]; - this._grid.batchUpdate(); - this._grid.column(this.options.column); - for (const item of items) { - const existingItem = gridItems.find(x => x.gridstackNode.id === item.identifier); - if (existingItem) { - elementsToRemove = elementsToRemove.filter(x => x.gridstackNode.id !== item.identifier); - this._grid.update(existingItem, { - h: item.height, - w: item.width, - x: item.x, - y: item.y, - }); - } else { - this._grid.addWidget(item.elementRef.nativeElement, { - id: item.identifier, - h: item.height, - w: item.width, - x: item.x, - y: item.y, - minW: item.minW, - minH: item.minH, - }); - } - } - for (const gridItemHTMLElement of elementsToRemove) { - this._grid.removeWidget(gridItemHTMLElement); - } - this._grid.commit(); - }); - this.update$.next(); - }); - } - - public ngOnDestroy(): void { - this.destroy$.next(true); - this.destroy$.complete(); - this.update$.complete(); - this._grid.destroy(); - } - - update() { - this.update$.next(); - } - - private hookEvents(grid: GridStack) { - grid.on('added', event => { - this.ngZone.run(() => { - this.gridstackAdded.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('disable', event => { - this.ngZone.run(() => { - this.gridstackDisable.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('enable', event => { - this.ngZone.run(() => { - this.gridstackEnable.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('removed', event => { - this.ngZone.run(() => { - this.gridstackRemoved.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('dropped', event => { - this.ngZone.run(() => { - this.gridstackDropped.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('resize', event => { - this.ngZone.run(() => { - this.gridstackResize.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('resizestart', event => { - this.ngZone.run(() => { - this.gridstackResizeStart.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('resizestop', event => { - this.ngZone.run(() => { - this.gridstackResizeStop.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('drag', event => { - this.ngZone.run(() => { - this.gridstackDrag.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('dragstart', event => { - this.ngZone.run(() => { - this.gridstackDragStart.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('dragstop', event => { - this.ngZone.run(() => { - this.gridstackDragStop.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - - grid.on('change', event => { - this.ngZone.run(() => { - this.gridstackChange.emit({ - event: event as unknown as GridStackEvent, - grid, - }); - }); - }); - } - -} diff --git a/demo/angular/gridstack.module.ts b/demo/angular/gridstack.module.ts deleted file mode 100644 index 44fd880d4..000000000 --- a/demo/angular/gridstack.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {NgModule} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {GridstackComponent} from './gridstack.component'; -import {GridstackItemComponent} from './gridstack-item.component'; - -@NgModule({ - declarations: [ - GridstackComponent, - GridstackItemComponent, - ], - exports: [ - GridstackComponent, - GridstackItemComponent, - ], - imports: [ - CommonModule, - ], -}) -export class GridstackModule { -} diff --git a/demo/angular/src/app/app.component.html b/demo/angular/src/app/app.component.html index ac1c36879..85fa0ae7b 100644 --- a/demo/angular/src/app/app.component.html +++ b/demo/angular/src/app/app.component.html @@ -4,10 +4,18 @@ +
+ + + + HELLO + + +
diff --git a/demo/angular/src/app/app.component.ts b/demo/angular/src/app/app.component.ts index c6ba4305a..f7cb8cb23 100644 --- a/demo/angular/src/app/app.component.ts +++ b/demo/angular/src/app/app.component.ts @@ -1,4 +1,6 @@ import { Component } from '@angular/core'; +import { GridStackOptions } from 'gridstack'; +import { elementCB, nodesCB } from './gridstack.component'; @Component({ selector: 'app-root', @@ -8,4 +10,17 @@ import { Component } from '@angular/core'; export class AppComponent { // which sample to show show = 1; + + public gridstackConfig: GridStackOptions = { + margin: 5, + float: true, + } + + public onChange(h: nodesCB) { + console.log('change ', h.nodes.length > 1 ? h.nodes : h.nodes[0]); + } + + public onResizeStop(h: elementCB) { + console.log('resizestop ', h.el.gridstackNode); + } } diff --git a/demo/angular/src/app/app.module.ts b/demo/angular/src/app/app.module.ts index 2099c524c..819ae41dd 100644 --- a/demo/angular/src/app/app.module.ts +++ b/demo/angular/src/app/app.module.ts @@ -2,6 +2,8 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; +import { GridstackItemComponent } from './gridstack-item.component'; +import { GridstackComponent } from './gridstack.component'; import { AngularNgForTestComponent } from './ngFor'; import { AngularNgForCmdTestComponent } from './ngFor_cmd'; import { AngularSimpleComponent } from './simple'; @@ -12,6 +14,8 @@ import { AngularSimpleComponent } from './simple'; AngularSimpleComponent, AngularNgForTestComponent, AngularNgForCmdTestComponent, + GridstackComponent, + GridstackItemComponent, ], imports: [ BrowserModule diff --git a/demo/angular/src/app/gridstack-item.component.ts b/demo/angular/src/app/gridstack-item.component.ts new file mode 100644 index 000000000..ce9637ef7 --- /dev/null +++ b/demo/angular/src/app/gridstack-item.component.ts @@ -0,0 +1,40 @@ +import {ChangeDetectionStrategy, Component, ElementRef, Input, OnInit, Renderer2} from '@angular/core'; +import { GridItemHTMLElement, numberOrString } from 'gridstack'; + +@Component({ + selector: 'gridstack-item', + template: ` +
+ +
`, + styles: [` + :host { display: block; } + `], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class GridstackItemComponent implements OnInit { + + @Input() public x: number; + @Input() public y: number; + @Input() public w: number; + @Input() public h: number; + @Input() public minW: number; + @Input() public minH: number; + @Input() public maxW: number; + @Input() public maxH: number; + @Input() public id: numberOrString; + + constructor( + private readonly _elementRef: ElementRef, + private readonly renderer2: Renderer2, + ) { + } + + get elementRef(): ElementRef { + return this._elementRef; + } + + public ngOnInit(): void { + this.renderer2.addClass(this._elementRef.nativeElement, 'grid-stack-item'); + } +} diff --git a/demo/angular/src/app/gridstack.component.ts b/demo/angular/src/app/gridstack.component.ts new file mode 100644 index 000000000..760a4bcac --- /dev/null +++ b/demo/angular/src/app/gridstack.component.ts @@ -0,0 +1,193 @@ +import { + ChangeDetectionStrategy, + Component, + ContentChildren, + ElementRef, + EventEmitter, + Input, + NgZone, + OnDestroy, + OnInit, + Output, + QueryList, + Renderer2, +} from '@angular/core'; +import { merge, Subject } from 'rxjs'; +import { map, takeUntil } from 'rxjs/operators'; +import { GridHTMLElement, GridItemHTMLElement, GridStack, GridStackNode, GridStackOptions } from 'gridstack'; + +import { GridstackItemComponent } from './gridstack-item.component'; + +/** events handlers emitters signature for different events */ +export type eventCB = {event: Event}; +export type elementCB = {event: Event, el: GridItemHTMLElement}; +export type nodesCB = {event: Event, nodes: GridStackNode[]}; +export type droppedCB = {event: Event, previousNode: GridStackNode, newNode: GridStackNode}; + +/** + * HTML Component Wrapper for gridstack, in combination with GridstackItemComponent for the items + */ +@Component({ + selector: 'gridstack', + template: '', + styles: [` + :host { display: block; } + `], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class GridstackComponent implements OnInit, OnDestroy { + + /** track list of grid items so we can sync between DOM and GS internals */ + @ContentChildren(GridstackItemComponent) public gridstackItems: QueryList; + + @Input() public options: GridStackOptions; + + /** individual list of all GridStackEvent callbacks handlers as output + * otherwise use this.grid.on('name1 name2 name3', callback) to handle multiple at once + * see https://github.com/gridstack/gridstack.js/blob/master/demo/events.js#L4 + */ + @Output() public addedCB = new EventEmitter(); + @Output() public changeCB = new EventEmitter(); + @Output() public disableCB = new EventEmitter(); + @Output() public dragCB = new EventEmitter(); + @Output() public dragstartCB = new EventEmitter(); + @Output() public dragstopCB = new EventEmitter(); + @Output() public droppedCB = new EventEmitter(); + @Output() public enableCB = new EventEmitter(); + @Output() public removedCB = new EventEmitter(); + @Output() public resizeCB = new EventEmitter(); + @Output() public resizestartCB = new EventEmitter(); + @Output() public resizestopCB = new EventEmitter(); + + public grid: GridStack; + private readonly update$ = new Subject(); + private readonly destroy$ = new Subject(); + + constructor( + private readonly ngZone: NgZone, + private readonly elementRef: ElementRef, + private readonly renderer2: Renderer2, + ) { + } + + public ngOnInit(): void { + this.renderer2.addClass(this.elementRef.nativeElement, 'grid-stack'); + } + + // wait until after DOM is ready to init gridstack - can't be ngOnInit() as angular ngFor or sub-components needs to run first! + public ngAfterContentInit(): void { + this.ngZone.runOutsideAngular(() => { + // initialize the grid with given options + this.grid = GridStack.init(this.options, this.elementRef.nativeElement); + this.hookEvents(this.grid); + + merge( + this.update$, + this.gridstackItems.changes, + ).pipe( + map(() => this.gridstackItems.toArray()), + takeUntil(this.destroy$), + ).subscribe(items => { + const gridItems = this.grid.getGridItems(); + let elementsToRemove = [...gridItems]; + this.grid.batchUpdate(); + // this.grid.column(this.options.column); + for (const item of items) { + const existingItem = gridItems.find(x => x.gridstackNode?.id === item.id); + if (existingItem) { + elementsToRemove = elementsToRemove.filter(x => x.gridstackNode?.id !== item.id); + this.grid.update(existingItem, { + h: item.h, + w: item.w, + x: item.x, + y: item.y, + }); + } else { + this.grid.addWidget(item.elementRef.nativeElement, { + id: item.id, + h: item.h, + w: item.w, + x: item.x, + y: item.y, + minW: item.minW, + minH: item.minH, + }); + } + } + for (const gridItemHTMLElement of elementsToRemove) { + this.grid.removeWidget(gridItemHTMLElement); + } + this.grid.commit(); + }); + + this.update$.next(); + }); + } + + public ngOnDestroy(): void { + this.destroy$.next(true); + this.destroy$.complete(); + this.update$.complete(); + this.grid.destroy(); + } + + public update() { + this.update$.next(); + } + + private hookEvents(grid: GridStack) { + grid.on('added', (event, nodes) => { + this.ngZone.run(() => this.addedCB.emit({event, nodes: nodes as GridStackNode[]})); + }); + + grid.on('change', (event, nodes) => { + this.ngZone.run(() => this.changeCB.emit({event, nodes: nodes as GridStackNode[]})); + }); + + grid.on('disable', (event) => { + this.ngZone.run(() => this.disableCB.emit({event})); + }); + + grid.on('drag', (event, el) => { + this.ngZone.run(() => this.dragCB.emit({event, el: el as GridItemHTMLElement})); + }); + + grid.on('dragstart', (event, el) => { + this.ngZone.run(() => this.dragstartCB.emit({event, el: el as GridItemHTMLElement})); + }); + + grid.on('dragstop', (event, el) => { + this.ngZone.run(() => this.dragstopCB.emit({event, el: el as GridItemHTMLElement})); + }); + + grid.on('dropped', (event, previousNode, newNode) => { + this.ngZone.run(() => + this.droppedCB.emit({ + event, + previousNode: previousNode as GridStackNode, + newNode: newNode as GridStackNode, + }) + ) + }); + + grid.on('enable', (event) => { + this.ngZone.run(() => this.enableCB.emit({event})); + }); + + grid.on('removed', (event, nodes) => { + this.ngZone.run(() => this.removedCB.emit({event, nodes: nodes as GridStackNode[]})); + }); + + grid.on('resize', (event, el) => { + this.ngZone.run(() => this.resizeCB.emit({event, el: el as GridItemHTMLElement})); + }); + + grid.on('resizestart', (event, el) => { + this.ngZone.run(() => this.resizestartCB.emit({event, el: el as GridItemHTMLElement})); + }); + + grid.on('resizestop', (event, el) => { + this.ngZone.run(() => this.resizestopCB.emit({event, el: el as GridItemHTMLElement})); + }); + } +}